Rename ext to lowlevel.
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/python/setup.py
40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/python/xen/__init__.py
-40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/ext/__init__.py
-3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/python/xen/ext/xc/Makefile
-3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/python/xen/ext/xc/setup.py
-3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/ext/xc/xc.c
-40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/ext/xu/__init__.py
-40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/ext/xu/domain_controller.h
-40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/ext/xu/xu.c
+40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/lowlevel/__init__.py
+3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/lowlevel/xc/xc.c
+40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/lowlevel/xu/__init__.py
+40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
+40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/python/xen/util/console_client.py
# -*- mode: Makefile; -*-
XEN_HYPERVISOR_IFS = $(XEN_ROOT)/xen/include/hypervisor-ifs
XEN_LINUX_INCLUDE = $(XEN_ROOT)/linux-xen-sparse/include
-XEN_XU = $(XEN_ROOT)/tools/python/xen/ext/xu
-XEN_XC = $(XEN_ROOT)/tools/python/xen/ext/xc
+XEN_XU = $(XEN_ROOT)/tools/python/xen/lowlevel/xu
+XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
XEN_LIBXC = $(XEN_ROOT)/tools/libxc
XEN_LIBXUTIL = $(XEN_ROOT)/tools/libxutil
include_dirs = [ XEN_ROOT + "/xen/include/hypervisor-ifs",
XEN_ROOT + "/linux-xen-sparse/include",
- XEN_ROOT + "/tools/python/xen/ext/xu",
+ XEN_ROOT + "/tools/python/xen/lowlevel/xu",
XEN_ROOT + "/tools/libxc",
XEN_ROOT + "/tools/libxutil",
]
xc = Extension("xc",
extra_compile_args = extra_compile_args,
- include_dirs = include_dirs + [ "xen/ext/xc" ],
+ include_dirs = include_dirs + [ "xen/lowlevel/xc" ],
library_dirs = library_dirs,
libraries = libraries,
- sources = [ "xen/ext/xc/xc.c" ])
+ sources = [ "xen/lowlevel/xc/xc.c" ])
xu = Extension("xu",
extra_compile_args = extra_compile_args,
- include_dirs = include_dirs + [ "xen/ext/xu" ],
+ include_dirs = include_dirs + [ "xen/lowlevel/xu" ],
library_dirs = library_dirs,
libraries = libraries,
- sources = [ "xen/ext/xu/xu.c" ])
+ sources = [ "xen/lowlevel/xu/xu.c" ])
setup(name = 'xen',
version = '2.0',
description = 'Xen',
packages = ['xen',
- 'xen.ext',
+ 'xen.lowlevel',
'xen.util',
'xen.xend',
'xen.xend.server',
'xen.xm',
],
- ext_package = "xen.ext",
+ ext_package = "xen.lowlevel",
ext_modules = [ xc, xu ]
)
+++ /dev/null
-
-all:
- python setup.py build
-
-install: all
- if [ "$(prefix)" = "" ]; then \
- python setup.py install; \
- elif [ "$(dist)" = "yes" ]; then \
- python setup.py install --home="$(prefix)"; \
- else \
- python setup.py install --root="$(prefix)"; \
- fi
-
-clean:
- rm -rf build *.pyc *.pyo *.o *.a *~
+++ /dev/null
-
-from distutils.core import setup, Extension
-
-module = Extension("xc",
- extra_compile_args = ["-fno-strict-aliasing"],
- include_dirs = ["../lib",
- "../../../xen/include/hypervisor-ifs",
- "../../../linux-xen-sparse/include",
- "../../xu/lib",
- "../../lib" ],
- library_dirs = ["../lib",
- "../../lib" ],
- libraries = ["xc"],
- sources = ["Xc.c"])
-
-setup(name = "xc",
- version = "2.0",
- ext_package = "xen.ext",
- ext_modules = [module])
+++ /dev/null
-/******************************************************************************
- * Xc.c
- *
- * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
- */
-
-#include <Python.h>
-#include <xc.h>
-#include <zlib.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include "xc_private.h"
-#include "gzip_stream.h"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-#define XENPKG "xen.ext.xc"
-
-static PyObject *xc_error, *zero;
-
-typedef struct {
- PyObject_HEAD;
- int xc_handle;
-} XcObject;
-
-/*
- * Definitions for the 'xc' object type.
- */
-
-static PyObject *pyxc_domain_create(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- unsigned int mem_kb = 0;
- char *name = "(anon)";
- int cpu = -1;
- u32 dom;
- int ret;
-
- static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list,
- &mem_kb, &name, &cpu) )
- return NULL;
-
- if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return PyInt_FromLong(dom);
-}
-
-static PyObject *pyxc_domain_pause(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
-
- static char *kwd_list[] = { "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
- return NULL;
-
- if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_domain_unpause(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
-
- static char *kwd_list[] = { "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
- return NULL;
-
- if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_domain_destroy(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
-
- static char *kwd_list[] = { "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
- return NULL;
-
- if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_domain_pincpu(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- int cpu = -1;
-
- static char *kwd_list[] = { "dom", "cpu", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &dom, &cpu) )
- return NULL;
-
- if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_domain_getinfo(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- PyObject *list;
-
- u32 first_dom = 0;
- int max_doms = 1024, nr_doms, i;
- xc_dominfo_t *info;
-
- static char *kwd_list[] = { "first_dom", "max_doms", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
- &first_dom, &max_doms) )
- return NULL;
-
- if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
- return PyErr_NoMemory();
-
- nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
-
- list = PyList_New(nr_doms);
- for ( i = 0 ; i < nr_doms; i++ )
- {
- PyList_SetItem(
- list, i,
- Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
- ",s:l,s:L,s:s,s:l,s:i}",
- "dom", info[i].domid,
- "cpu", info[i].cpu,
- "dying", info[i].dying,
- "crashed", info[i].crashed,
- "shutdown", info[i].shutdown,
- "paused", info[i].paused,
- "blocked", info[i].blocked,
- "running", info[i].running,
- "mem_kb", info[i].nr_pages*4,
- "cpu_time", info[i].cpu_time,
- "name", info[i].name,
- "maxmem_kb", info[i].max_memkb,
- "shutdown_reason", info[i].shutdown_reason
- ));
- }
-
- free(info);
-
- return list;
-}
-
-static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
-{
- int rc = -1;
- int fd = -1;
- int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
- int open_mode = 0644;
-
- printf("%s>\n", __FUNCTION__);
-
- if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
- {
- xcio_perror(ctxt, "Could not open file for writing");
- goto exit;
- }
-
- printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
-
- /* Compression rate 1: we want speed over compression.
- * We're mainly going for those zero pages, after all.
- */
- ctxt->io = gzip_stream_fdopen(fd, "wb1");
- if ( ctxt->io == NULL )
- {
- xcio_perror(ctxt, "Could not allocate compression state");
- goto exit;
- }
-
- printf("%s> xc_linux_save...\n", __FUNCTION__);
-
- rc = xc_linux_save(xc->xc_handle, ctxt);
-
- exit:
- if ( ctxt->io != NULL )
- IOStream_close(ctxt->io);
- if ( fd >= 0 )
- close(fd);
- unlink(state_file);
- printf("%s> rc=%d\n", __FUNCTION__, rc);
- return rc;
-}
-
-static PyObject *pyxc_linux_save(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- char *state_file;
- int progress = 1, debug = 0;
- PyObject *val = NULL;
- int rc = -1;
- XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-
- static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list,
- &ioctxt.domain,
- &state_file,
- &ioctxt.vmconfig,
- &progress,
- &debug) )
- goto exit;
-
- ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
-
- if ( progress )
- ioctxt.flags |= XCFLAGS_VERBOSE;
- if ( debug )
- ioctxt.flags |= XCFLAGS_DEBUG;
-
- if ( (state_file == NULL) || (state_file[0] == '\0') )
- goto exit;
-
- rc = file_save(xc, &ioctxt, state_file);
- if ( rc != 0 )
- {
- PyErr_SetFromErrno(xc_error);
- goto exit;
- }
-
- Py_INCREF(zero);
- val = zero;
-
- exit:
- return val;
-}
-
-
-static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
-{
- int rc = -1;
-
- ioctxt->io = gzip_stream_fopen(state_file, "rb");
- if ( ioctxt->io == NULL )
- {
- xcio_perror(ioctxt, "Could not open file for reading");
- return rc;
- }
-
- rc = xc_linux_restore(xc->xc_handle, ioctxt);
-
- IOStream_close(ioctxt->io);
-
- return rc;
-}
-
-static PyObject *pyxc_linux_restore(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- char *state_file;
- int progress = 1, debug = 0;
- PyObject *val = NULL;
- XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
- int rc =-1;
-
- static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list,
- &ioctxt.domain,
- &state_file,
- &progress,
- &debug) )
- goto exit;
-
- if ( progress )
- ioctxt.flags |= XCFLAGS_VERBOSE;
- if ( debug )
- ioctxt.flags |= XCFLAGS_DEBUG;
-
- if ( (state_file == NULL) || (state_file[0] == '\0') )
- goto exit;
-
- rc = file_restore(xc, &ioctxt, state_file);
- if ( rc != 0 )
- {
- PyErr_SetFromErrno(xc_error);
- goto exit;
- }
-
- val = Py_BuildValue("{s:i,s:s}",
- "dom", ioctxt.domain,
- "vmconfig", ioctxt.vmconfig);
-
- exit:
- return val;
-}
-
-static PyObject *pyxc_linux_build(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- char *image, *ramdisk = NULL, *cmdline = "";
- int control_evtchn, flags = 0;
-
- static char *kwd_list[] = { "dom", "control_evtchn",
- "image", "ramdisk", "cmdline", "flags",
- NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
- &dom, &control_evtchn,
- &image, &ramdisk, &cmdline, &flags) )
- return NULL;
-
- if ( xc_linux_build(xc->xc_handle, dom, image,
- ramdisk, cmdline, control_evtchn, flags) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_netbsd_build(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- char *image, *ramdisk = NULL, *cmdline = "";
- int control_evtchn;
-
- static char *kwd_list[] = { "dom", "control_evtchn",
- "image", "ramdisk", "cmdline", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
- &dom, &control_evtchn,
- &image, &ramdisk, &cmdline) )
- return NULL;
-
- if ( xc_netbsd_build(xc->xc_handle, dom, image,
- cmdline, control_evtchn) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_set(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- unsigned long ctx_allow;
-
- static char *kwd_list[] = { "ctx_allow", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
- return NULL;
-
- if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_get(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- unsigned long ctx_allow;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
-}
-
-static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- unsigned long mcuadv, warp, warpl, warpu;
-
- static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
- "warpu", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
- &dom, &mcuadv, &warp, &warpl, &warpu) )
- return NULL;
-
- if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
- warp, warpl, warpu) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u32 dom;
- unsigned long mcuadv, warp, warpl, warpu;
-
- static char *kwd_list[] = { "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
- return NULL;
-
- if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
- &warpl, &warpu) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
- "domain", dom,
- "mcuadv", mcuadv,
- "warp", warp,
- "warpl", warpl,
- "warpu", warpu);
-}
-
-static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
- int port1, port2;
-
- static char *kwd_list[] = { "dom1", "dom2", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
- &dom1, &dom2) )
- return NULL;
-
- if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
- dom2, &port1, &port2) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i,s:i}",
- "port1", port1,
- "port2", port2);
-}
-
-static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- int virq, port;
-
- static char *kwd_list[] = { "virq", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
- return NULL;
-
- if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return PyInt_FromLong(port);
-}
-
-static PyObject *pyxc_evtchn_close(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom = DOMID_SELF;
- int port;
-
- static char *kwd_list[] = { "port", "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &port, &dom) )
- return NULL;
-
- if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_evtchn_send(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- int port;
-
- static char *kwd_list[] = { "port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
- return NULL;
-
- if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_evtchn_status(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- PyObject *dict;
-
- u32 dom = DOMID_SELF;
- int port, ret;
- xc_evtchn_status_t status;
-
- static char *kwd_list[] = { "port", "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &port, &dom) )
- return NULL;
-
- ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
- if ( ret != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- switch ( status.status )
- {
- case EVTCHNSTAT_closed:
- dict = Py_BuildValue("{s:s}",
- "status", "closed");
- break;
- case EVTCHNSTAT_unbound:
- dict = Py_BuildValue("{s:s}",
- "status", "unbound");
- break;
- case EVTCHNSTAT_interdomain:
- dict = Py_BuildValue("{s:s,s:i,s:i}",
- "status", "interdomain",
- "dom", status.u.interdomain.dom,
- "port", status.u.interdomain.port);
- break;
- case EVTCHNSTAT_pirq:
- dict = Py_BuildValue("{s:s,s:i}",
- "status", "pirq",
- "irq", status.u.pirq);
- break;
- case EVTCHNSTAT_virq:
- dict = Py_BuildValue("{s:s,s:i}",
- "status", "virq",
- "irq", status.u.virq);
- break;
- default:
- dict = Py_BuildValue("{}");
- break;
- }
-
- return dict;
-}
-
-static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u32 dom;
- int bus, dev, func, enable, ret;
-
- static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
- &dom, &bus, &dev, &func, &enable) )
- return NULL;
-
- ret = xc_physdev_pci_access_modify(
- xc->xc_handle, dom, bus, dev, func, enable);
- if ( ret != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_readconsolering(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- unsigned int clear = 0;
- char str[32768];
- int ret;
-
- static char *kwd_list[] = { "clear", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
- return NULL;
-
- ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
- if ( ret < 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return PyString_FromStringAndSize(str, ret);
-}
-
-static PyObject *pyxc_physinfo(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- xc_physinfo_t info;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( xc_physinfo(xc->xc_handle, &info) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
- "ht_per_core", info.ht_per_core,
- "cores", info.cores,
- "total_pages", info.total_pages,
- "free_pages", info.free_pages,
- "cpu_khz", info.cpu_khz);
-}
-
-static PyObject *pyxc_atropos_domain_set(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u32 domid;
- u64 period, slice, latency;
- int xtratime;
-
- static char *kwd_list[] = { "dom", "period", "slice", "latency",
- "xtratime", NULL };
-
- if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
- &period, &slice, &latency, &xtratime) )
- return NULL;
-
- if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
- latency, xtratime) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_atropos_domain_get(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u32 domid;
- u64 period, slice, latency;
- int xtratime;
-
- static char *kwd_list[] = { "dom", NULL };
-
- if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
- return NULL;
-
- if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
- &slice, &latency, &xtratime ) )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
- "domain", domid,
- "period", period,
- "slice", slice,
- "latency", latency,
- "xtratime", xtratime);
-}
-
-
-static PyObject *pyxc_rrobin_global_set(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u64 slice;
-
- static char *kwd_list[] = { "slice", NULL };
-
- if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
- return NULL;
-
- if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_shadow_control(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- int op=0;
-
- static char *kwd_list[] = { "dom", "op", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &dom, &op) )
- return NULL;
-
- if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_rrobin_global_get(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u64 slice;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:L}", "slice", slice);
-}
-
-static PyObject *pyxc_domain_setname(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
- u32 dom;
- char *name;
-
- static char *kwd_list[] = { "dom", "name", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
- &dom, &name) )
- return NULL;
-
- if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_domain_setmaxmem(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom;
- unsigned long max_memkb;
-
- static char *kwd_list[] = { "dom", "max_memkb", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
- &dom, &max_memkb) )
- return NULL;
-
- if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-
-static PyMethodDef pyxc_methods[] = {
- { "domain_create",
- (PyCFunction)pyxc_domain_create,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Create a new domain.\n"
- " mem_kb [int, 0]: Memory allocation, in kilobytes.\n"
- " name [str, '(anon)']: Informative textual name.\n\n"
- "Returns: [int] new domain identifier; -1 on error.\n" },
-
- { "domain_pause",
- (PyCFunction)pyxc_domain_pause,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Temporarily pause execution of a domain.\n"
- " dom [int]: Identifier of domain to be paused.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_unpause",
- (PyCFunction)pyxc_domain_unpause,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "(Re)start execution of a domain.\n"
- " dom [int]: Identifier of domain to be unpaused.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_destroy",
- (PyCFunction)pyxc_domain_destroy,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Destroy a domain.\n"
- " dom [int]: Identifier of domain to be destroyed.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_pincpu",
- (PyCFunction)pyxc_domain_pincpu,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Pin a domain to a specified CPU.\n"
- " dom [int]: Identifier of domain to be pinned.\n"
- " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_getinfo",
- (PyCFunction)pyxc_domain_getinfo,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Get information regarding a set of domains, in increasing id order.\n"
- " first_dom [int, 0]: First domain to retrieve info about.\n"
- " max_doms [int, 1024]: Maximum number of domains to retrieve info"
- " about.\n\n"
- "Returns: [list of dicts] if list length is less than 'max_doms'\n"
- " parameter then there was an error, or the end of the\n"
- " domain-id space was reached.\n"
- " dom [int]: Identifier of domain to which this info pertains\n"
- " cpu [int]: CPU to which this domain is bound\n"
- " dying [int]: Bool - is the domain dying?\n"
- " crashed [int]: Bool - has the domain crashed?\n"
- " shutdown [int]: Bool - has the domain shut itself down?\n"
- " paused [int]: Bool - is the domain paused by control software?\n"
- " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
- " running [int]: Bool - is the domain currently running?\n"
- " mem_kb [int]: Memory reservation, in kilobytes\n"
- " cpu_time [long]: CPU time consumed, in nanoseconds\n"
- " name [str]: Identifying name\n"
- " shutdown_reason [int]: Numeric code from guest OS, explaining "
- "reason why it shut itself down.\n" },
-
- { "linux_save",
- (PyCFunction)pyxc_linux_save,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Save the CPU and memory state of a Linux guest OS.\n"
- " dom [int]: Identifier of domain to be saved.\n"
- " state_file [str]: Name of state file. Must not currently exist.\n"
- " progress [int, 1]: Bool - display a running progress indication?\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "linux_restore",
- (PyCFunction)pyxc_linux_restore,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Restore the CPU and memory state of a Linux guest OS.\n"
- " state_file [str]: Name of state file. Must not currently exist.\n"
- " progress [int, 1]: Bool - display a running progress indication?\n\n"
- "Returns: [int] new domain identifier on success; -1 on error.\n" },
-
- { "linux_build",
- (PyCFunction)pyxc_linux_build,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Build a new Linux guest OS.\n"
- " dom [int]: Identifier of domain to build into.\n"
- " image [str]: Name of kernel image file. May be gzipped.\n"
- " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
- " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "netbsd_build",
- (PyCFunction)pyxc_netbsd_build,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Build a new NetBSD guest OS.\n"
- " dom [int]: Identifier of domain to build into.\n"
- " image [str]: Name of kernel image file. May be gzipped.\n"
- " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "bvtsched_global_set",
- (PyCFunction)pyxc_bvtsched_global_set,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
- " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "bvtsched_global_get",
- (PyCFunction)pyxc_bvtsched_global_get,
- METH_KEYWORDS, "\n"
- "Get global tuning parameters for BVT scheduler.\n"
- "Returns: [dict]:\n"
- " ctx_allow [int]: context switch allowance\n" },
-
- { "bvtsched_domain_set",
- (PyCFunction)pyxc_bvtsched_domain_set,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
- " dom [int]: Identifier of domain to be tuned.\n"
- " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
- " warp [int]: How far to warp domain's EVT on unblock.\n"
- " warpl [int]: How long the domain can run warped.\n"
- " warpu [int]: How long before the domain can warp again.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "bvtsched_domain_get",
- (PyCFunction)pyxc_bvtsched_domain_get,
- METH_KEYWORDS, "\n"
- "Get per-domain tuning parameters under the BVT scheduler.\n"
- " dom [int]: Identifier of domain to be queried.\n"
- "Returns [dict]:\n"
- " domain [int]: Domain ID.\n"
- " mcuadv [long]: MCU Advance.\n"
- " warp [long]: Warp.\n"
- " warpu [long]: Unwarp requirement.\n"
- " warpl [long]: Warp limit,\n"
- },
-
- { "atropos_domain_set",
- (PyCFunction)pyxc_atropos_domain_set,
- METH_KEYWORDS, "\n"
- "Set the scheduling parameters for a domain when running with Atropos.\n"
- " dom [int]: domain to set\n"
- " period [long]: domain's scheduling period\n"
- " slice [long]: domain's slice per period\n"
- " latency [long]: wakeup latency hint\n"
- " xtratime [int]: boolean\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "atropos_domain_get",
- (PyCFunction)pyxc_atropos_domain_get,
- METH_KEYWORDS, "\n"
- "Get the current scheduling parameters for a domain when running with\n"
- "the Atropos scheduler."
- " dom [int]: domain to query\n"
- "Returns: [dict]\n"
- " domain [int]: domain ID\n"
- " period [long]: scheduler period\n"
- " slice [long]: CPU reservation per period\n"
- " latency [long]: unblocking latency hint\n"
- " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
-
- { "rrobin_global_set",
- (PyCFunction)pyxc_rrobin_global_set,
- METH_KEYWORDS, "\n"
- "Set Round Robin scheduler slice.\n"
- " slice [long]: Round Robin scheduler slice\n"
- "Returns: [int] 0 on success, throws an exception on failure\n" },
-
- { "rrobin_global_get",
- (PyCFunction)pyxc_rrobin_global_get,
- METH_KEYWORDS, "\n"
- "Get Round Robin scheduler settings\n"
- "Returns [dict]:\n"
- " slice [long]: Scheduler time slice.\n" },
-
- { "evtchn_bind_interdomain",
- (PyCFunction)pyxc_evtchn_bind_interdomain,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Open an event channel between two domains.\n"
- " dom1 [int, SELF]: First domain to be connected.\n"
- " dom2 [int, SELF]: Second domain to be connected.\n\n"
- "Returns: [dict] dictionary is empty on failure.\n"
- " port1 [int]: Port-id for endpoint at dom1.\n"
- " port2 [int]: Port-id for endpoint at dom2.\n" },
-
- { "evtchn_bind_virq",
- (PyCFunction)pyxc_evtchn_bind_virq,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Bind an event channel to the specified VIRQ.\n"
- " virq [int]: VIRQ to bind.\n\n"
- "Returns: [int] Bound event-channel port.\n" },
-
- { "evtchn_close",
- (PyCFunction)pyxc_evtchn_close,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Close an event channel.\n"
- " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
- " port [int]: Port-id of one endpoint of the channel.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "evtchn_send",
- (PyCFunction)pyxc_evtchn_send,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Send an event along a locally-connected event channel.\n"
- " port [int]: Port-id of a local channel endpoint.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "evtchn_status",
- (PyCFunction)pyxc_evtchn_status,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Query the status of an event channel.\n"
- " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
- " port [int]: Port-id of one endpoint of the channel.\n\n"
- "Returns: [dict] dictionary is empty on failure.\n"
- " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
- " or 'virq'.\n"
- "The following are returned if 'status' is 'interdomain':\n"
- " dom [int]: Dom-id of remote endpoint.\n"
- " port [int]: Port-id of remote endpoint.\n"
- "The following are returned if 'status' is 'pirq' or 'virq':\n"
- " irq [int]: IRQ number.\n" },
-
- { "physdev_pci_access_modify",
- (PyCFunction)pyxc_physdev_pci_access_modify,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Allow a domain access to a PCI device\n"
- " dom [int]: Identifier of domain to be allowed access.\n"
- " bus [int]: PCI bus\n"
- " dev [int]: PCI slot\n"
- " func [int]: PCI function\n"
- " enable [int]: Non-zero means enable access; else disable access\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "readconsolering",
- (PyCFunction)pyxc_readconsolering,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Read Xen's console ring.\n"
- " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
- "Returns: [str] string is empty on failure.\n" },
-
- { "physinfo",
- (PyCFunction)pyxc_physinfo,
- METH_VARARGS, "\n"
- "Get information about the physical host machine\n"
- "Returns [dict]: information about the hardware"
- " [None]: on failure.\n" },
-
- { "shadow_control",
- (PyCFunction)pyxc_shadow_control,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set parameter for shadow pagetable interface\n"
- " dom [int]: Identifier of domain.\n"
- " op [int, 0]: operation\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_setname",
- (PyCFunction)pyxc_domain_setname,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set domain informative textual name\n"
- " dom [int]: Identifier of domain.\n"
- " name [str]: Text string.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "domain_setmaxmem",
- (PyCFunction)pyxc_domain_setmaxmem,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set a domain's memory limit\n"
- " dom [int]: Identifier of domain.\n"
- " max_memkb [long]: .\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-
-/*
- * Definitions for the 'Xc' module wrapper.
- */
-
-staticforward PyTypeObject PyXcType;
-
-static PyObject *PyXc_new(PyObject *self, PyObject *args)
-{
- XcObject *xc;
-
- if ( !PyArg_ParseTuple(args, ":new") )
- return NULL;
-
- xc = PyObject_New(XcObject, &PyXcType);
-
- if ( (xc->xc_handle = xc_interface_open()) == -1 )
- {
- PyObject_Del((PyObject *)xc);
- return PyErr_SetFromErrno(xc_error);
- }
-
- return (PyObject *)xc;
-}
-
-static PyObject *PyXc_getattr(PyObject *obj, char *name)
-{
- return Py_FindMethod(pyxc_methods, obj, name);
-}
-
-static void PyXc_dealloc(PyObject *self)
-{
- XcObject *xc = (XcObject *)self;
- (void)xc_interface_close(xc->xc_handle);
- PyObject_Del(self);
-}
-
-static PyTypeObject PyXcType = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "Xc",
- sizeof(XcObject),
- 0,
- PyXc_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- PyXc_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-static PyMethodDef PyXc_methods[] = {
- { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
- { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxc(void)
-{
- PyObject *m, *d;
-
- m = Py_InitModule(XENPKG, PyXc_methods);
-
- d = PyModule_GetDict(m);
- xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
- PyDict_SetItemString(d, "error", xc_error);
-
- zero = PyInt_FromLong(0);
-}
+++ /dev/null
-/******************************************************************************
- * domain_controller.h
- *
- * Interface to server controller (e.g., 'xend'). This header file defines the
- * interface that is shared with guest OSes.
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __DOMAIN_CONTROLLER_H__
-#define __DOMAIN_CONTROLLER_H__
-
-
-#ifndef BASIC_START_INFO
-#error "Xen header file hypervisor-if.h must already be included here."
-#endif
-
-
-/*
- * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
- */
-
-typedef struct {
- BASIC_START_INFO;
- u16 domain_controller_evtchn; /* 320 */
-} PACKED extended_start_info_t; /* 322 bytes */
-#define SIF_BLK_BE_DOMAIN (1<<4) /* Is this a block backend domain? */
-#define SIF_NET_BE_DOMAIN (1<<5) /* Is this a net backend domain? */
-
-
-/*
- * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
- * interpreted by control software to determine the appropriate action. These
- * are only really advisories: the controller can actually do as it likes.
- */
-#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
-#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
-
-
-/*
- * CONTROLLER MESSAGING INTERFACE.
- */
-
-typedef struct {
- u8 type; /* 0: echoed in response */
- u8 subtype; /* 1: echoed in response */
- u8 id; /* 2: echoed in response */
- u8 length; /* 3: number of bytes in 'msg' */
- u8 msg[60]; /* 4: type-specific message data */
-} PACKED control_msg_t; /* 64 bytes */
-
-#define CONTROL_RING_SIZE 8
-typedef u32 CONTROL_RING_IDX;
-#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
-
-typedef struct {
- control_msg_t tx_ring[CONTROL_RING_SIZE]; /* 0: guest -> controller */
- control_msg_t rx_ring[CONTROL_RING_SIZE]; /* 512: controller -> guest */
- CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
- CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
-} PACKED control_if_t; /* 1040 bytes */
-
-/*
- * Top-level command types.
- */
-#define CMSG_CONSOLE 0 /* Console */
-#define CMSG_BLKIF_BE 1 /* Block-device backend */
-#define CMSG_BLKIF_FE 2 /* Block-device frontend */
-#define CMSG_NETIF_BE 3 /* Network-device backend */
-#define CMSG_NETIF_FE 4 /* Network-device frontend */
-#define CMSG_SHUTDOWN 6 /* Shutdown messages */
-
-
-/******************************************************************************
- * CONSOLE DEFINITIONS
- */
-
-/*
- * Subtypes for console messages.
- */
-#define CMSG_CONSOLE_DATA 0
-
-
-/******************************************************************************
- * BLOCK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED 0
-
-/* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED 32
-#define CMSG_BLKIF_FE_INTERFACE_CONNECT 33
-#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT 34
-
-/* These are used by both front-end and back-end drivers. */
-#define blkif_vdev_t u16
-#define blkif_pdev_t u16
-#define blkif_sector_t u64
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
- * Notify a guest about a status change on one of its block interfaces.
- * If the interface is DESTROYED or DOWN then the interface is disconnected:
- * 1. The shared-memory frame is available for reuse.
- * 2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
-#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
-typedef struct {
- u32 handle; /* 0 */
- u32 status; /* 4 */
- u16 evtchn; /* 8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
-} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
-
-/*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
- * Notify the domain controller that the front-end driver is DOWN or UP.
- * When the driver goes DOWN then the controller will send no more
- * status-change notifications. When the driver comes UP then the controller
- * will send a notification for each interface that currently exists.
- * If the driver goes DOWN while interfaces are still UP, the domain
- * will automatically take the interfaces DOWN.
- */
-#define BLKIF_DRIVER_STATUS_DOWN 0
-#define BLKIF_DRIVER_STATUS_UP 1
-typedef struct {
- /* IN */
- u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */
- /* OUT */
- /*
- * Tells driver how many interfaces it should expect to immediately
- * receive notifications about.
- */
- u32 nr_interfaces; /* 4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_CONNECT:
- * If successful, the domain controller will acknowledge with a
- * STATUS_CONNECTED message.
- */
-typedef struct {
- u32 handle; /* 0 */
- u32 __pad;
- memory_t shmem_frame; /* 8 */
- MEMORY_PADDING;
-} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
- * If successful, the domain controller will acknowledge with a
- * STATUS_DISCONNECTED message.
- */
-typedef struct {
- u32 handle; /* 0 */
-} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * BLOCK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_BLKIF_BE_CREATE 0 /* Create a new block-device interface. */
-#define CMSG_BLKIF_BE_DESTROY 1 /* Destroy a block-device interface. */
-#define CMSG_BLKIF_BE_CONNECT 2 /* Connect i/f to remote driver. */
-#define CMSG_BLKIF_BE_DISCONNECT 3 /* Disconnect i/f from remote driver. */
-#define CMSG_BLKIF_BE_VBD_CREATE 4 /* Create a new VBD for an interface. */
-#define CMSG_BLKIF_BE_VBD_DESTROY 5 /* Delete a VBD from an interface. */
-#define CMSG_BLKIF_BE_VBD_GROW 6 /* Append an extent to a given VBD. */
-#define CMSG_BLKIF_BE_VBD_SHRINK 7 /* Remove last extent from a given VBD. */
-
-/* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for block-device messages.
- */
-
-typedef struct {
- blkif_sector_t sector_start; /* 0 */
- blkif_sector_t sector_length; /* 8 */
- blkif_pdev_t device; /* 16 */
- u16 __pad; /* 18 */
-} PACKED blkif_extent_t; /* 20 bytes */
-
-/* Non-specific 'okay' return. */
-#define BLKIF_BE_STATUS_OKAY 0
-/* Non-specific 'error' return. */
-#define BLKIF_BE_STATUS_ERROR 1
-/* The following are specific error returns. */
-#define BLKIF_BE_STATUS_INTERFACE_EXISTS 2
-#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define BLKIF_BE_STATUS_VBD_EXISTS 5
-#define BLKIF_BE_STATUS_VBD_NOT_FOUND 6
-#define BLKIF_BE_STATUS_OUT_OF_MEMORY 7
-#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND 8
-#define BLKIF_BE_STATUS_MAPPING_ERROR 9
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define BLKIF_BE_STATUS_ERRORS { \
- "Okay", \
- "Non-specific error", \
- "Interface already exists", \
- "Interface not found", \
- "Interface is still connected", \
- "VBD already exists", \
- "VBD not found", \
- "Out of memory", \
- "Extent not found for VBD", \
- "Could not map domain memory" }
-
-/*
- * CMSG_BLKIF_BE_CREATE:
- * When the driver sends a successful response then the interface is fully
- * created. The controller will send a DOWN notification to the front-end
- * driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 blkif_handle; /* 4: Domain-specific interface handle. */
- /* OUT */
- u32 status; /* 8 */
-} PACKED blkif_be_create_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_DESTROY:
- * When the driver sends a successful response then the interface is fully
- * torn down. The controller will send a DESTROYED notification to the
- * front-end driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify interface to be destroyed. */
- u32 blkif_handle; /* 4: ...ditto... */
- /* OUT */
- u32 status; /* 8 */
-} PACKED blkif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_CONNECT:
- * When the driver sends a successful response then the interface is fully
- * connected. The controller will send a CONNECTED notification to the
- * front-end driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 blkif_handle; /* 4: Domain-specific interface handle. */
- memory_t shmem_frame; /* 8: Page cont. shared comms window. */
- MEMORY_PADDING;
- u32 evtchn; /* 16: Event channel for notifications. */
- /* OUT */
- u32 status; /* 20 */
-} PACKED blkif_be_connect_t; /* 24 bytes */
-
-/*
- * CMSG_BLKIF_BE_DISCONNECT:
- * When the driver sends a successful response then the interface is fully
- * disconnected. The controller will send a DOWN notification to the front-end
- * driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 blkif_handle; /* 4: Domain-specific interface handle. */
- /* OUT */
- u32 status; /* 8 */
-} PACKED blkif_be_disconnect_t; /* 12 bytes */
-
-/* CMSG_BLKIF_BE_VBD_CREATE */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify blkdev interface. */
- u32 blkif_handle; /* 4: ...ditto... */
- blkif_vdev_t vdevice; /* 8: Interface-specific id for this VBD. */
- u16 readonly; /* 10: Non-zero -> VBD isn't writeable. */
- /* OUT */
- u32 status; /* 12 */
-} PACKED blkif_be_vbd_create_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_DESTROY */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify blkdev interface. */
- u32 blkif_handle; /* 4: ...ditto... */
- blkif_vdev_t vdevice; /* 8: Interface-specific id of the VBD. */
- u16 __pad; /* 10 */
- /* OUT */
- u32 status; /* 12 */
-} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_GROW */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify blkdev interface. */
- u32 blkif_handle; /* 4: ...ditto... */
- blkif_extent_t extent; /* 8: Physical extent to append to VBD. */
- blkif_vdev_t vdevice; /* 28: Interface-specific id of the VBD. */
- u16 __pad; /* 30 */
- /* OUT */
- u32 status; /* 32 */
-} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
-
-/* CMSG_BLKIF_BE_VBD_SHRINK */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify blkdev interface. */
- u32 blkif_handle; /* 4: ...ditto... */
- blkif_vdev_t vdevice; /* 8: Interface-specific id of the VBD. */
- u16 __pad; /* 10 */
- /* OUT */
- u32 status; /* 12 */
-} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
- * Notify the domain controller that the back-end driver is DOWN or UP.
- * If the driver goes DOWN while interfaces are still UP, the controller
- * will automatically send DOWN notifications.
- */
-typedef struct {
- u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED 0
-
-/* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED 32
-#define CMSG_NETIF_FE_INTERFACE_CONNECT 33
-#define CMSG_NETIF_FE_INTERFACE_DISCONNECT 34
-
-/*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
- * Notify a guest about a status change on one of its network interfaces.
- * If the interface is DESTROYED or DOWN then the interface is disconnected:
- * 1. The shared-memory frame is available for reuse.
- * 2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
-#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
-typedef struct {
- u32 handle; /* 0 */
- u32 status; /* 4 */
- u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */
- u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
-} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
-
-/*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
- * Notify the domain controller that the front-end driver is DOWN or UP.
- * When the driver goes DOWN then the controller will send no more
- * status-change notifications. When the driver comes UP then the controller
- * will send a notification for each interface that currently exists.
- * If the driver goes DOWN while interfaces are still UP, the domain
- * will automatically take the interfaces DOWN.
- */
-#define NETIF_DRIVER_STATUS_DOWN 0
-#define NETIF_DRIVER_STATUS_UP 1
-typedef struct {
- /* IN */
- u32 status; /* 0: NETIF_DRIVER_STATUS_??? */
- /* OUT */
- /*
- * Tells driver how many interfaces it should expect to immediately
- * receive notifications about.
- */
- u32 nr_interfaces; /* 4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_CONNECT:
- * If successful, the domain controller will acknowledge with a
- * STATUS_CONNECTED message.
- */
-typedef struct {
- u32 handle; /* 0 */
- u32 __pad; /* 4 */
- memory_t tx_shmem_frame; /* 8 */
- MEMORY_PADDING;
- memory_t rx_shmem_frame; /* 16 */
- MEMORY_PADDING;
-} PACKED netif_fe_interface_connect_t; /* 24 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
- * If successful, the domain controller will acknowledge with a
- * STATUS_DISCONNECTED message.
- */
-typedef struct {
- u32 handle; /* 0 */
-} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_NETIF_BE_CREATE 0 /* Create a new net-device interface. */
-#define CMSG_NETIF_BE_DESTROY 1 /* Destroy a net-device interface. */
-#define CMSG_NETIF_BE_CONNECT 2 /* Connect i/f to remote driver. */
-#define CMSG_NETIF_BE_DISCONNECT 3 /* Disconnect i/f from remote driver. */
-
-/* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for net-device messages.
- */
-
-/* Non-specific 'okay' return. */
-#define NETIF_BE_STATUS_OKAY 0
-/* Non-specific 'error' return. */
-#define NETIF_BE_STATUS_ERROR 1
-/* The following are specific error returns. */
-#define NETIF_BE_STATUS_INTERFACE_EXISTS 2
-#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define NETIF_BE_STATUS_OUT_OF_MEMORY 5
-#define NETIF_BE_STATUS_MAPPING_ERROR 6
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define NETIF_BE_STATUS_ERRORS { \
- "Okay", \
- "Non-specific error", \
- "Interface already exists", \
- "Interface not found", \
- "Interface is still connected", \
- "Out of memory", \
- "Could not map domain memory" }
-
-/*
- * CMSG_NETIF_BE_CREATE:
- * When the driver sends a successful response then the interface is fully
- * created. The controller will send a DOWN notification to the front-end
- * driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 netif_handle; /* 4: Domain-specific interface handle. */
- u8 mac[6]; /* 8 */
- u16 __pad; /* 14 */
- /* OUT */
- u32 status; /* 16 */
-} PACKED netif_be_create_t; /* 20 bytes */
-
-/*
- * CMSG_NETIF_BE_DESTROY:
- * When the driver sends a successful response then the interface is fully
- * torn down. The controller will send a DESTROYED notification to the
- * front-end driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Identify interface to be destroyed. */
- u32 netif_handle; /* 4: ...ditto... */
- /* OUT */
- u32 status; /* 8 */
-} PACKED netif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_CONNECT:
- * When the driver sends a successful response then the interface is fully
- * connected. The controller will send a CONNECTED notification to the
- * front-end driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 netif_handle; /* 4: Domain-specific interface handle. */
- memory_t tx_shmem_frame; /* 8: Page cont. tx shared comms window. */
- MEMORY_PADDING;
- memory_t rx_shmem_frame; /* 16: Page cont. rx shared comms window. */
- MEMORY_PADDING;
- u16 evtchn; /* 24: Event channel for notifications. */
- u16 __pad; /* 26 */
- /* OUT */
- u32 status; /* 28 */
-} PACKED netif_be_connect_t; /* 32 bytes */
-
-/*
- * CMSG_NETIF_BE_DISCONNECT:
- * When the driver sends a successful response then the interface is fully
- * disconnected. The controller will send a DOWN notification to the front-end
- * driver.
- */
-typedef struct {
- /* IN */
- domid_t domid; /* 0: Domain attached to new interface. */
- u32 netif_handle; /* 4: Domain-specific interface handle. */
- /* OUT */
- u32 status; /* 8 */
-} PACKED netif_be_disconnect_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
- * Notify the domain controller that the back-end driver is DOWN or UP.
- * If the driver goes DOWN while interfaces are still UP, the domain
- * will automatically send DOWN notifications.
- */
-typedef struct {
- u32 status; /* 0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * SHUTDOWN DEFINITIONS
- */
-
-/*
- * Subtypes for shutdown messages.
- */
-#define CMSG_SHUTDOWN_POWEROFF 0 /* Clean shutdown (SHUTDOWN_poweroff). */
-#define CMSG_SHUTDOWN_REBOOT 1 /* Clean shutdown (SHUTDOWN_reboot). */
-#define CMSG_SHUTDOWN_SUSPEND 2 /* Create suspend info, then */
- /* SHUTDOWN_suspend. */
-
-#endif /* __DOMAIN_CONTROLLER_H__ */
+++ /dev/null
-/******************************************************************************
- * utils.c
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xc.h>
-
-#include <hypervisor-if.h>
-#include "domain_controller.h"
-
-#include <asm-xen/proc_cmd.h>
-
-#define XENPKG "xen.ext.xu"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 200
-#define PORT_NORMAL 0x0000 /* A standard event notification. */
-#define PORT_EXCEPTION 0x8000 /* An exceptional notification. */
-#define PORTIDX_MASK 0x7fff /* Strip subtype to obtain port index. */
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE 4096
-
-
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
- PyObject_HEAD;
- int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- u16 v;
- int bytes;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
- {
- if ( errno == EINTR )
- continue;
- if ( errno == EAGAIN )
- goto none;
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- if ( bytes == sizeof(v) )
- return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
-
- none:
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- u16 v;
- int idx;
-
- if ( !PyArg_ParseTuple(args, "i", &idx) )
- return NULL;
-
- v = (u16)idx;
-
- (void)write(xun->evtchn_fd, &v, sizeof(v));
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- int idx;
-
- if ( !PyArg_ParseTuple(args, "i", &idx) )
- return NULL;
-
- if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
- return PyErr_SetFromErrno(PyExc_IOError);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- int idx;
-
- if ( !PyArg_ParseTuple(args, "i", &idx) )
- return NULL;
-
- if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
- return PyErr_SetFromErrno(PyExc_IOError);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- return PyInt_FromLong(xun->evtchn_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
- { "read",
- (PyCFunction)xu_notifier_read,
- METH_VARARGS,
- "Read a (@port, @type) pair.\n" },
-
- { "unmask",
- (PyCFunction)xu_notifier_unmask,
- METH_VARARGS,
- "Unmask notifications for a @port.\n" },
-
- { "bind",
- (PyCFunction)xu_notifier_bind,
- METH_VARARGS,
- "Get notifications for a @port.\n" },
-
- { "unbind",
- (PyCFunction)xu_notifier_unbind,
- METH_VARARGS,
- "No longer get notifications for a @port.\n" },
-
- { "fileno",
- (PyCFunction)xu_notifier_fileno,
- METH_VARARGS,
- "Return the file descriptor for the notification channel.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
- reopen:
- xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
- if ( xun->evtchn_fd == -1 )
- {
- if ( (errno == ENOENT) &&
- ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
- (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
- (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
- goto reopen;
- PyObject_Del((PyObject *)xun);
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
- if ( strcmp(name, "EXCEPTION") == 0 )
- return PyInt_FromLong(PORT_EXCEPTION);
- if ( strcmp(name, "NORMAL") == 0 )
- return PyInt_FromLong(PORT_NORMAL);
- return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- (void)close(xun->evtchn_fd);
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "notifier",
- sizeof(xu_notifier_object),
- 0,
- xu_notifier_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_notifier_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-#define P2C(_struct, _field, _ctype) \
- do { \
- PyObject *obj; \
- if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
- { \
- if ( PyInt_Check(obj) ) \
- { \
- ((_struct *)&xum->msg.msg[0])->_field = \
- (_ctype)PyInt_AsLong(obj); \
- dict_items_parsed++; \
- } \
- else if ( PyLong_Check(obj) ) \
- { \
- ((_struct *)&xum->msg.msg[0])->_field = \
- (_ctype)PyLong_AsUnsignedLongLong(obj); \
- dict_items_parsed++; \
- } \
- } \
- xum->msg.length = sizeof(_struct); \
- } while ( 0 )
-#define C2P(_struct, _field, _pytype, _ctype) \
- do { \
- PyObject *obj = Py ## _pytype ## _From ## _ctype \
- (((_struct *)&xum->msg.msg[0])->_field); \
- if ( dict == NULL ) dict = PyDict_New(); \
- PyDict_SetItemString(dict, #_field, obj); \
- } while ( 0 )
-
-typedef struct {
- PyObject_HEAD;
- control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- char *str;
- int len;
-
- if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
- return NULL;
-
- if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
- {
- PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
- return NULL;
- }
-
- memcpy(&xum->msg.msg[xum->msg.length], str, len);
- xum->msg.length += len;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- PyObject *payload;
- int dict_items_parsed = 0;
-
- if ( !PyArg_ParseTuple(args, "O", &payload) )
- return NULL;
-
- if ( !PyDict_Check(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
- return NULL;
- }
-
- switch ( TYPE(xum->msg.type, xum->msg.subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
- P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
- P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
- break;
- }
-
- if ( dict_items_parsed != PyDict_Size(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload contains bad items");
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- PyObject *dict = NULL;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- switch ( TYPE(xum->msg.type, xum->msg.subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
- C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
- C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
- C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
- C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
- C2P(blkif_fe_interface_connect_t, handle, Int, Long);
- C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
- C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
- C2P(blkif_be_create_t, domid, Int, Long);
- C2P(blkif_be_create_t, blkif_handle, Int, Long);
- C2P(blkif_be_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
- C2P(blkif_be_destroy_t, domid, Int, Long);
- C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
- C2P(blkif_be_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
- C2P(blkif_be_connect_t, domid, Int, Long);
- C2P(blkif_be_connect_t, blkif_handle, Int, Long);
- C2P(blkif_be_connect_t, shmem_frame, Int, Long);
- C2P(blkif_be_connect_t, evtchn, Int, Long);
- C2P(blkif_be_connect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
- C2P(blkif_be_disconnect_t, domid, Int, Long);
- C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
- C2P(blkif_be_disconnect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
- C2P(blkif_be_vbd_create_t, domid, Int, Long);
- C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_create_t, readonly, Int, Long);
- C2P(blkif_be_vbd_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
- C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
- C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
- C2P(blkif_be_vbd_grow_t, domid, Int, Long);
- C2P(blkif_be_vbd_grow_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_grow_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_grow_t, extent.sector_start,
- Long, UnsignedLongLong);
- C2P(blkif_be_vbd_grow_t, extent.sector_length,
- Long, UnsignedLongLong);
- C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
- C2P(blkif_be_vbd_grow_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
- C2P(blkif_be_vbd_shrink_t, domid, Int, Long);
- C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_shrink_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
- C2P(blkif_be_driver_status_changed_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
- C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
- C2P(netif_fe_interface_status_changed_t, status, Int, Long);
- C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
- C2P(netif_fe_driver_status_changed_t, status, Int, Long);
- C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
- C2P(netif_fe_interface_connect_t, handle, Int, Long);
- C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
- C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
- C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
- C2P(netif_be_create_t, domid, Int, Long);
- C2P(netif_be_create_t, netif_handle, Int, Long);
- C2P(netif_be_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
- C2P(netif_be_destroy_t, domid, Int, Long);
- C2P(netif_be_destroy_t, netif_handle, Int, Long);
- C2P(netif_be_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
- C2P(netif_be_connect_t, domid, Int, Long);
- C2P(netif_be_connect_t, netif_handle, Int, Long);
- C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
- C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
- C2P(netif_be_connect_t, evtchn, Int, Long);
- C2P(netif_be_connect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
- C2P(netif_be_disconnect_t, domid, Int, Long);
- C2P(netif_be_disconnect_t, netif_handle, Int, Long);
- C2P(netif_be_disconnect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
- C2P(netif_be_driver_status_changed_t, status, Int, Long);
- return dict;
- }
-
- return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- return Py_BuildValue("{s:i,s:i,s:i}",
- "type", xum->msg.type,
- "subtype", xum->msg.subtype,
- "id", xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
- { "append_payload",
- (PyCFunction)xu_message_append_payload,
- METH_VARARGS,
- "Append @str to the message payload.\n" },
-
- { "set_response_fields",
- (PyCFunction)xu_message_set_response_fields,
- METH_VARARGS,
- "Fill in the response fields in a message that was passed to us.\n" },
-
- { "get_payload",
- (PyCFunction)xu_message_get_payload,
- METH_VARARGS,
- "Return the message payload in string form.\n" },
-
- { "get_header",
- (PyCFunction)xu_message_get_header,
- METH_VARARGS,
- "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
- xu_message_object *xum;
- int type, subtype, id, dict_items_parsed = 0;
- PyObject *payload = NULL;
-
- if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
- return NULL;
-
- xum = PyObject_New(xu_message_object, &xu_message_type);
-
- xum->msg.type = type;
- xum->msg.subtype = subtype;
- xum->msg.id = id;
- xum->msg.length = 0;
-
- if ( payload == NULL )
- return (PyObject *)xum;
-
- if ( !PyDict_Check(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
- PyObject_Del((PyObject *)xum);
- return NULL;
- }
-
- switch ( TYPE(type, subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
- P2C(blkif_fe_interface_status_changed_t, handle, u32);
- P2C(blkif_fe_interface_status_changed_t, status, u32);
- P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
- P2C(blkif_be_create_t, domid, u32);
- P2C(blkif_be_create_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
- P2C(blkif_be_destroy_t, domid, u32);
- P2C(blkif_be_destroy_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
- P2C(blkif_be_connect_t, domid, u32);
- P2C(blkif_be_connect_t, blkif_handle, u32);
- P2C(blkif_be_connect_t, shmem_frame, memory_t);
- P2C(blkif_be_connect_t, evtchn, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
- P2C(blkif_be_disconnect_t, domid, u32);
- P2C(blkif_be_disconnect_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
- P2C(blkif_be_vbd_create_t, domid, u32);
- P2C(blkif_be_vbd_create_t, blkif_handle, u32);
- P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
- P2C(blkif_be_vbd_create_t, readonly, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
- P2C(blkif_be_vbd_destroy_t, domid, u32);
- P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
- P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
- P2C(blkif_be_vbd_grow_t, domid, u32);
- P2C(blkif_be_vbd_grow_t, blkif_handle, u32);
- P2C(blkif_be_vbd_grow_t, vdevice, blkif_vdev_t);
- P2C(blkif_be_vbd_grow_t, extent.sector_start, blkif_sector_t);
- P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
- P2C(blkif_be_vbd_grow_t, extent.device, blkif_pdev_t);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
- P2C(blkif_be_vbd_shrink_t, domid, u32);
- P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
- P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
- P2C(netif_fe_interface_status_changed_t, handle, u32);
- P2C(netif_fe_interface_status_changed_t, status, u32);
- P2C(netif_fe_interface_status_changed_t, evtchn, u16);
- P2C(netif_fe_interface_status_changed_t, mac[0], u8);
- P2C(netif_fe_interface_status_changed_t, mac[1], u8);
- P2C(netif_fe_interface_status_changed_t, mac[2], u8);
- P2C(netif_fe_interface_status_changed_t, mac[3], u8);
- P2C(netif_fe_interface_status_changed_t, mac[4], u8);
- P2C(netif_fe_interface_status_changed_t, mac[5], u8);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
- P2C(netif_be_create_t, domid, u32);
- P2C(netif_be_create_t, netif_handle, u32);
- P2C(netif_be_create_t, mac[0], u8);
- P2C(netif_be_create_t, mac[1], u8);
- P2C(netif_be_create_t, mac[2], u8);
- P2C(netif_be_create_t, mac[3], u8);
- P2C(netif_be_create_t, mac[4], u8);
- P2C(netif_be_create_t, mac[5], u8);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
- P2C(netif_be_destroy_t, domid, u32);
- P2C(netif_be_destroy_t, netif_handle, u32);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
- P2C(netif_be_connect_t, domid, u32);
- P2C(netif_be_connect_t, netif_handle, u32);
- P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
- P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
- P2C(netif_be_connect_t, evtchn, u16);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
- P2C(netif_be_disconnect_t, domid, u32);
- P2C(netif_be_disconnect_t, netif_handle, u32);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
- P2C(netif_fe_driver_status_changed_t, status, u32);
- P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
- break;
- }
-
- if ( dict_items_parsed != PyDict_Size(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload contains bad items");
- PyObject_Del((PyObject *)xum);
- return NULL;
- }
-
- return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
- xu_message_object *xum;
- if ( strcmp(name, "MAX_PAYLOAD") == 0 )
- return PyInt_FromLong(sizeof(xum->msg.msg));
- return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "message",
- sizeof(xu_message_object),
- 0,
- xu_message_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_message_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn)
-{
- char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
- MAP_SHARED, fd, pfn * PAGE_SIZE);
- if ( vaddr == MAP_FAILED )
- return NULL;
- return (control_if_t *)(vaddr + 2048);
-}
-static void unmap_control_interface(int fd, control_if_t *c)
-{
- char *vaddr = (char *)c - 2048;
- (void)munmap(vaddr, PAGE_SIZE);
-}
-
-typedef struct xu_port_object {
- PyObject_HEAD;
- int mem_fd;
- int xc_handle;
- u32 remote_dom;
- int local_port, remote_port;
- control_if_t *interface;
- CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
- CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static int xup_connect(xu_port_object *xup, domid_t dom,
- int local_port, int remote_port){
- // From our prespective rx = producer, tx = consumer.
- int err = 0;
- printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom,
- local_port, remote_port);
-
- // Consumer = tx.
- //xup->interface->tx_resp_prod = 0;
- //xup->interface->tx_req_prod = 0;
- xup->tx_resp_prod = xup->interface->tx_resp_prod;
- xup->tx_req_cons = xup->interface->tx_resp_prod;
- printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
- (unsigned int)xup->interface->tx_resp_prod,
- (unsigned int)xup->tx_resp_prod,
- (unsigned int)xup->tx_req_cons,
- (unsigned int)xup->interface->tx_req_prod);
-
- // Producer = rx.
- //xup->interface->rx_req_prod = 0;
- //xup->interface->rx_resp_prod = 0;
- xup->rx_req_prod = xup->interface->rx_req_prod;
- xup->rx_resp_cons = xup->interface->rx_resp_prod;
- printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
- (unsigned int)xup->rx_resp_cons,
- (unsigned int)xup->interface->rx_resp_prod,
- (unsigned int)xup->interface->rx_req_prod,
- (unsigned int)xup->rx_req_prod);
-
- xup->remote_dom = dom;
- xup->local_port = local_port;
- xup->remote_port = remote_port;
-
- printf("%s< err=%d\n", __FUNCTION__, err);
- return err;
-}
-
-static PyObject *xu_port_notify(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- CONTROL_RING_IDX c = xup->tx_req_cons;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->tx_req_prod) ||
- ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
- {
- PyErr_SetString(port_error, "no request to read");
- return NULL;
- }
-
- cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
- xum = PyObject_New(xu_message_object, &xu_message_type);
- memcpy(&xum->msg, cmsg, sizeof(*cmsg));
- if ( xum->msg.length > sizeof(xum->msg.msg) )
- xum->msg.length = sizeof(xum->msg.msg);
- xup->tx_req_cons++;
- return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- CONTROL_RING_IDX p = xup->rx_req_prod;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
- return NULL;
-
- if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
- {
- PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
- return NULL;
- }
-
- if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
- {
- PyErr_SetString(port_error, "no space to write request");
- return NULL;
- }
-
- cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
- memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
- xup->rx_req_prod = cif->rx_req_prod = p + 1;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- CONTROL_RING_IDX c = xup->rx_resp_cons;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
- {
- PyErr_SetString(port_error, "no response to read");
- return NULL;
- }
-
- cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
- xum = PyObject_New(xu_message_object, &xu_message_type);
- memcpy(&xum->msg, cmsg, sizeof(*cmsg));
- if ( xum->msg.length > sizeof(xum->msg.msg) )
- xum->msg.length = sizeof(xum->msg.msg);
- xup->rx_resp_cons++;
- return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- CONTROL_RING_IDX p = xup->tx_resp_prod;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
- return NULL;
-
- if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
- {
- PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
- return NULL;
- }
-
- if ( p == xup->tx_req_cons )
- {
- PyErr_SetString(port_error, "no space to write response");
- return NULL;
- }
-
- cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
- memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
- xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX c = xup->tx_req_cons;
- control_if_t *cif = xup->interface;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->tx_req_prod) ||
- ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX p = xup->rx_req_prod;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX c = xup->rx_resp_cons;
- control_if_t *cif = xup->interface;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_response(
- PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX p = xup->tx_resp_prod;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( p == xup->tx_req_cons )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
-}
-
-static PyMethodDef xu_port_methods[] = {
- { "notify",
- (PyCFunction)xu_port_notify,
- METH_VARARGS,
- "Send a notification to the remote end.\n" },
-
- { "read_request",
- (PyCFunction)xu_port_read_request,
- METH_VARARGS,
- "Read a request message from the control interface.\n" },
-
- { "write_request",
- (PyCFunction)xu_port_write_request,
- METH_VARARGS,
- "Write a request message to the control interface.\n" },
-
- { "read_response",
- (PyCFunction)xu_port_read_response,
- METH_VARARGS,
- "Read a response message from the control interface.\n" },
-
- { "write_response",
- (PyCFunction)xu_port_write_response,
- METH_VARARGS,
- "Write a response message to the control interface.\n" },
-
- { "request_to_read",
- (PyCFunction)xu_port_request_to_read,
- METH_VARARGS,
- "Returns TRUE if there is a request message to read.\n" },
-
- { "space_to_write_request",
- (PyCFunction)xu_port_space_to_write_request,
- METH_VARARGS,
- "Returns TRUE if there is space to write a request message.\n" },
-
- { "response_to_read",
- (PyCFunction)xu_port_response_to_read,
- METH_VARARGS,
- "Returns TRUE if there is a response message to read.\n" },
-
- { "space_to_write_response",
- (PyCFunction)xu_port_space_to_write_response,
- METH_VARARGS,
- "Returns TRUE if there is space to write a response message.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args)
-{
- xu_port_object *xup;
- u32 dom;
- int port1, port2;
- xc_dominfo_t info;
-
- if ( !PyArg_ParseTuple(args, "i", &dom) )
- return NULL;
-
- xup = PyObject_New(xu_port_object, &xu_port_type);
-
- if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
- {
- PyErr_SetString(port_error, "Could not open '/dev/mem'");
- goto fail1;
- }
-
- /* Set the General-Purpose Subject whose page frame will be mapped. */
- (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
-
- if ( (xup->xc_handle = xc_interface_open()) == -1 )
- {
- PyErr_SetString(port_error, "Could not open Xen control interface");
- goto fail2;
- }
-
- if ( dom == 0 )
- {
- /*
- * The control-interface event channel for DOM0 is already set up.
- * We use an ioctl to discover the port at our end of the channel.
- */
- port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
- port2 = -1; /* We don't need the remote end of the DOM0 link. */
- if ( port1 < 0 )
- {
- PyErr_SetString(port_error, "Could not open channel to DOM0");
- goto fail3;
- }
- }
- else if ( xc_evtchn_bind_interdomain(xup->xc_handle,
- DOMID_SELF, dom,
- &port1, &port2) != 0 )
- {
- PyErr_SetString(port_error, "Could not open channel to domain");
- goto fail3;
- }
-
- if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
- (info.domid != dom) )
- {
- PyErr_SetString(port_error, "Failed to obtain domain status");
- goto fail4;
- }
-
- xup->interface =
- map_control_interface(xup->mem_fd, info.shared_info_frame);
- if ( xup->interface == NULL )
- {
- PyErr_SetString(port_error, "Failed to map domain control interface");
- goto fail4;
- }
-
- xup_connect(xup, dom, port1, port2);
- return (PyObject *)xup;
-
-
- fail4:
- (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
- fail3:
- (void)xc_interface_close(xup->xc_handle);
- fail2:
- (void)close(xup->mem_fd);
- fail1:
- PyObject_Del((PyObject *)xup);
- return NULL;
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
- xu_port_object *xup = (xu_port_object *)obj;
- if ( strcmp(name, "local_port") == 0 )
- return PyInt_FromLong(xup->local_port);
- if ( strcmp(name, "remote_port") == 0 )
- return PyInt_FromLong(xup->remote_port);
- if ( strcmp(name, "remote_dom") == 0 )
- return PyInt_FromLong(xup->remote_dom);
- return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
- xu_port_object *xup = (xu_port_object *)self;
- unmap_control_interface(xup->mem_fd, xup->interface);
- if ( xup->remote_dom != 0 )
- (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
- (void)xc_interface_close(xup->xc_handle);
- (void)close(xup->mem_fd);
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "port",
- sizeof(xu_port_object),
- 0,
- xu_port_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_port_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
- PyObject_HEAD;
- char *buf;
- unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
- PyObject *str1, *str2;
- int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
- len1 = xub->prod - xub->cons;
- if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
- len1 = BUFSZ - c;
- if ( len1 > max ) /* clip to specified maximum */
- len1 = max;
- if ( len1 < 0 ) /* sanity */
- len1 = 0;
-
- if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
- return NULL;
-
- if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
- {
- len2 = max - len1;
- if ( len2 > MASK_BUF_IDX(xub->prod) )
- len2 = MASK_BUF_IDX(xub->prod);
- if ( len2 > 0 )
- {
- str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
- if ( str2 == NULL )
- return NULL;
- PyString_ConcatAndDel(&str1, str2);
- if ( str1 == NULL )
- return NULL;
- }
- }
-
- return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- int max = 1024;
-
- if ( !PyArg_ParseTuple(args, "|i", &max) )
- return NULL;
-
- return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- PyObject *str;
- int max = 1024;
-
- if ( !PyArg_ParseTuple(args, "|i", &max) )
- return NULL;
-
- if ( (str = __xu_buffer_peek(xub, max)) != NULL )
- xub->cons += PyString_Size(str);
-
- return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- int max, len;
-
- if ( !PyArg_ParseTuple(args, "i", &max) )
- return NULL;
-
- len = xub->prod - xub->cons;
- if ( len > max )
- len = max;
- if ( len < 0 )
- len = 0;
-
- xub->cons += len;
-
- return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- char *str;
- int len, len1, len2;
-
- if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
- return NULL;
-
- len1 = len;
- if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
- len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
- if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
- len1 = BUFSZ - (xub->prod - xub->cons);
-
- if ( len1 == 0 )
- return PyInt_FromLong(0);
-
- memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
- xub->prod += len1;
-
- if ( len1 < len )
- {
- len2 = len - len1;
- if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
- len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
- if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
- len2 = BUFSZ - (xub->prod - xub->cons);
- if ( len2 != 0 )
- {
- memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
- xub->prod += len2;
- return PyInt_FromLong(len1 + len2);
- }
- }
-
- return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( xub->cons == xub->prod )
- return PyInt_FromLong(1);
-
- return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (xub->prod - xub->cons) == BUFSZ )
- return PyInt_FromLong(1);
-
- return PyInt_FromLong(0);
-}
-
-static PyMethodDef xu_buffer_methods[] = {
- { "peek",
- (PyCFunction)xu_buffer_peek,
- METH_VARARGS,
- "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
- { "read",
- (PyCFunction)xu_buffer_read,
- METH_VARARGS,
- "Read up to @max bytes from the buffer. Returns a string.\n" },
-
- { "discard",
- (PyCFunction)xu_buffer_discard,
- METH_VARARGS,
- "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
- { "write",
- (PyCFunction)xu_buffer_write,
- METH_VARARGS,
- "Write @string into buffer. Return number of bytes written.\n" },
-
- { "empty",
- (PyCFunction)xu_buffer_empty,
- METH_VARARGS,
- "Return TRUE if the buffer is empty.\n" },
-
- { "full",
- (PyCFunction)xu_buffer_full,
- METH_VARARGS,
- "Return TRUE if the buffer is full.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
- if ( (xub->buf = malloc(BUFSZ)) == NULL )
- {
- PyObject_Del((PyObject *)xub);
- return NULL;
- }
-
- xub->prod = xub->cons = 0;
-
- return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
- return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- free(xub->buf);
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "buffer",
- sizeof(xu_buffer_object),
- 0,
- xu_buffer_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_buffer_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
- while ( waitpid(-1, NULL, WNOHANG) > 0 )
- continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
- struct sigaction sa;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = handle_child_death;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
- (void)sigaction(SIGCHLD, &sa, NULL);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
- { "notifier", xu_notifier_new, METH_VARARGS,
- "Create a new notifier." },
- { "message", xu_message_new, METH_VARARGS,
- "Create a new communications message." },
- { "port", xu_port_new, METH_VARARGS,
- "Create a new communications port." },
- { "buffer", xu_buffer_new, METH_VARARGS,
- "Create a new ring buffer." },
- { "autoreap", xu_autoreap, METH_VARARGS,
- "Ensure that zombie children are automatically reaped by the OS." },
- { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxu(void)
-{
- PyObject *m, *d;
-
- m = Py_InitModule(XENPKG, xu_methods);
-
- d = PyModule_GetDict(m);
- port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
- PyDict_SetItemString(d, "PortError", port_error);
-}
--- /dev/null
+/******************************************************************************
+ * Xc.c
+ *
+ * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
+ */
+
+#include <Python.h>
+#include <xc.h>
+#include <zlib.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "xc_private.h"
+#include "gzip_stream.h"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+#define XENPKG "xen.lowlevel.xc"
+
+static PyObject *xc_error, *zero;
+
+typedef struct {
+ PyObject_HEAD;
+ int xc_handle;
+} XcObject;
+
+/*
+ * Definitions for the 'xc' object type.
+ */
+
+static PyObject *pyxc_domain_create(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ unsigned int mem_kb = 0;
+ char *name = "(anon)";
+ int cpu = -1;
+ u32 dom;
+ int ret;
+
+ static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list,
+ &mem_kb, &name, &cpu) )
+ return NULL;
+
+ if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return PyInt_FromLong(dom);
+}
+
+static PyObject *pyxc_domain_pause(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+
+ static char *kwd_list[] = { "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+ return NULL;
+
+ if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_unpause(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+
+ static char *kwd_list[] = { "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+ return NULL;
+
+ if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_destroy(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+
+ static char *kwd_list[] = { "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+ return NULL;
+
+ if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_pincpu(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ int cpu = -1;
+
+ static char *kwd_list[] = { "dom", "cpu", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
+ &dom, &cpu) )
+ return NULL;
+
+ if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_getinfo(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ PyObject *list;
+
+ u32 first_dom = 0;
+ int max_doms = 1024, nr_doms, i;
+ xc_dominfo_t *info;
+
+ static char *kwd_list[] = { "first_dom", "max_doms", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
+ &first_dom, &max_doms) )
+ return NULL;
+
+ if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
+ return PyErr_NoMemory();
+
+ nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
+
+ list = PyList_New(nr_doms);
+ for ( i = 0 ; i < nr_doms; i++ )
+ {
+ PyList_SetItem(
+ list, i,
+ Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
+ ",s:l,s:L,s:s,s:l,s:i}",
+ "dom", info[i].domid,
+ "cpu", info[i].cpu,
+ "dying", info[i].dying,
+ "crashed", info[i].crashed,
+ "shutdown", info[i].shutdown,
+ "paused", info[i].paused,
+ "blocked", info[i].blocked,
+ "running", info[i].running,
+ "mem_kb", info[i].nr_pages*4,
+ "cpu_time", info[i].cpu_time,
+ "name", info[i].name,
+ "maxmem_kb", info[i].max_memkb,
+ "shutdown_reason", info[i].shutdown_reason
+ ));
+ }
+
+ free(info);
+
+ return list;
+}
+
+static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
+{
+ int rc = -1;
+ int fd = -1;
+ int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
+ int open_mode = 0644;
+
+ printf("%s>\n", __FUNCTION__);
+
+ if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
+ {
+ xcio_perror(ctxt, "Could not open file for writing");
+ goto exit;
+ }
+
+ printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
+
+ /* Compression rate 1: we want speed over compression.
+ * We're mainly going for those zero pages, after all.
+ */
+ ctxt->io = gzip_stream_fdopen(fd, "wb1");
+ if ( ctxt->io == NULL )
+ {
+ xcio_perror(ctxt, "Could not allocate compression state");
+ goto exit;
+ }
+
+ printf("%s> xc_linux_save...\n", __FUNCTION__);
+
+ rc = xc_linux_save(xc->xc_handle, ctxt);
+
+ exit:
+ if ( ctxt->io != NULL )
+ IOStream_close(ctxt->io);
+ if ( fd >= 0 )
+ close(fd);
+ unlink(state_file);
+ printf("%s> rc=%d\n", __FUNCTION__, rc);
+ return rc;
+}
+
+static PyObject *pyxc_linux_save(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ char *state_file;
+ int progress = 1, debug = 0;
+ PyObject *val = NULL;
+ int rc = -1;
+ XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+
+ static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list,
+ &ioctxt.domain,
+ &state_file,
+ &ioctxt.vmconfig,
+ &progress,
+ &debug) )
+ goto exit;
+
+ ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
+
+ if ( progress )
+ ioctxt.flags |= XCFLAGS_VERBOSE;
+ if ( debug )
+ ioctxt.flags |= XCFLAGS_DEBUG;
+
+ if ( (state_file == NULL) || (state_file[0] == '\0') )
+ goto exit;
+
+ rc = file_save(xc, &ioctxt, state_file);
+ if ( rc != 0 )
+ {
+ PyErr_SetFromErrno(xc_error);
+ goto exit;
+ }
+
+ Py_INCREF(zero);
+ val = zero;
+
+ exit:
+ return val;
+}
+
+
+static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
+{
+ int rc = -1;
+
+ ioctxt->io = gzip_stream_fopen(state_file, "rb");
+ if ( ioctxt->io == NULL )
+ {
+ xcio_perror(ioctxt, "Could not open file for reading");
+ return rc;
+ }
+
+ rc = xc_linux_restore(xc->xc_handle, ioctxt);
+
+ IOStream_close(ioctxt->io);
+
+ return rc;
+}
+
+static PyObject *pyxc_linux_restore(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ char *state_file;
+ int progress = 1, debug = 0;
+ PyObject *val = NULL;
+ XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+ int rc =-1;
+
+ static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list,
+ &ioctxt.domain,
+ &state_file,
+ &progress,
+ &debug) )
+ goto exit;
+
+ if ( progress )
+ ioctxt.flags |= XCFLAGS_VERBOSE;
+ if ( debug )
+ ioctxt.flags |= XCFLAGS_DEBUG;
+
+ if ( (state_file == NULL) || (state_file[0] == '\0') )
+ goto exit;
+
+ rc = file_restore(xc, &ioctxt, state_file);
+ if ( rc != 0 )
+ {
+ PyErr_SetFromErrno(xc_error);
+ goto exit;
+ }
+
+ val = Py_BuildValue("{s:i,s:s}",
+ "dom", ioctxt.domain,
+ "vmconfig", ioctxt.vmconfig);
+
+ exit:
+ return val;
+}
+
+static PyObject *pyxc_linux_build(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ char *image, *ramdisk = NULL, *cmdline = "";
+ int control_evtchn, flags = 0;
+
+ static char *kwd_list[] = { "dom", "control_evtchn",
+ "image", "ramdisk", "cmdline", "flags",
+ NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
+ &dom, &control_evtchn,
+ &image, &ramdisk, &cmdline, &flags) )
+ return NULL;
+
+ if ( xc_linux_build(xc->xc_handle, dom, image,
+ ramdisk, cmdline, control_evtchn, flags) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_netbsd_build(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ char *image, *ramdisk = NULL, *cmdline = "";
+ int control_evtchn;
+
+ static char *kwd_list[] = { "dom", "control_evtchn",
+ "image", "ramdisk", "cmdline", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
+ &dom, &control_evtchn,
+ &image, &ramdisk, &cmdline) )
+ return NULL;
+
+ if ( xc_netbsd_build(xc->xc_handle, dom, image,
+ cmdline, control_evtchn) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_set(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ unsigned long ctx_allow;
+
+ static char *kwd_list[] = { "ctx_allow", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
+ return NULL;
+
+ if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_get(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ unsigned long ctx_allow;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
+}
+
+static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ unsigned long mcuadv, warp, warpl, warpu;
+
+ static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
+ "warpu", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
+ &dom, &mcuadv, &warp, &warpl, &warpu) )
+ return NULL;
+
+ if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
+ warp, warpl, warpu) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u32 dom;
+ unsigned long mcuadv, warp, warpl, warpu;
+
+ static char *kwd_list[] = { "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+ return NULL;
+
+ if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
+ &warpl, &warpu) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
+ "domain", dom,
+ "mcuadv", mcuadv,
+ "warp", warp,
+ "warpl", warpl,
+ "warpu", warpu);
+}
+
+static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
+ int port1, port2;
+
+ static char *kwd_list[] = { "dom1", "dom2", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
+ &dom1, &dom2) )
+ return NULL;
+
+ if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
+ dom2, &port1, &port2) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:i}",
+ "port1", port1,
+ "port2", port2);
+}
+
+static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ int virq, port;
+
+ static char *kwd_list[] = { "virq", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
+ return NULL;
+
+ if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return PyInt_FromLong(port);
+}
+
+static PyObject *pyxc_evtchn_close(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom = DOMID_SELF;
+ int port;
+
+ static char *kwd_list[] = { "port", "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
+ &port, &dom) )
+ return NULL;
+
+ if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_evtchn_send(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ int port;
+
+ static char *kwd_list[] = { "port", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
+ return NULL;
+
+ if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_evtchn_status(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ PyObject *dict;
+
+ u32 dom = DOMID_SELF;
+ int port, ret;
+ xc_evtchn_status_t status;
+
+ static char *kwd_list[] = { "port", "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
+ &port, &dom) )
+ return NULL;
+
+ ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
+ if ( ret != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ switch ( status.status )
+ {
+ case EVTCHNSTAT_closed:
+ dict = Py_BuildValue("{s:s}",
+ "status", "closed");
+ break;
+ case EVTCHNSTAT_unbound:
+ dict = Py_BuildValue("{s:s}",
+ "status", "unbound");
+ break;
+ case EVTCHNSTAT_interdomain:
+ dict = Py_BuildValue("{s:s,s:i,s:i}",
+ "status", "interdomain",
+ "dom", status.u.interdomain.dom,
+ "port", status.u.interdomain.port);
+ break;
+ case EVTCHNSTAT_pirq:
+ dict = Py_BuildValue("{s:s,s:i}",
+ "status", "pirq",
+ "irq", status.u.pirq);
+ break;
+ case EVTCHNSTAT_virq:
+ dict = Py_BuildValue("{s:s,s:i}",
+ "status", "virq",
+ "irq", status.u.virq);
+ break;
+ default:
+ dict = Py_BuildValue("{}");
+ break;
+ }
+
+ return dict;
+}
+
+static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u32 dom;
+ int bus, dev, func, enable, ret;
+
+ static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
+ &dom, &bus, &dev, &func, &enable) )
+ return NULL;
+
+ ret = xc_physdev_pci_access_modify(
+ xc->xc_handle, dom, bus, dev, func, enable);
+ if ( ret != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_readconsolering(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ unsigned int clear = 0;
+ char str[32768];
+ int ret;
+
+ static char *kwd_list[] = { "clear", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
+ return NULL;
+
+ ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+ if ( ret < 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return PyString_FromStringAndSize(str, ret);
+}
+
+static PyObject *pyxc_physinfo(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ xc_physinfo_t info;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xc_physinfo(xc->xc_handle, &info) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
+ "ht_per_core", info.ht_per_core,
+ "cores", info.cores,
+ "total_pages", info.total_pages,
+ "free_pages", info.free_pages,
+ "cpu_khz", info.cpu_khz);
+}
+
+static PyObject *pyxc_atropos_domain_set(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u32 domid;
+ u64 period, slice, latency;
+ int xtratime;
+
+ static char *kwd_list[] = { "dom", "period", "slice", "latency",
+ "xtratime", NULL };
+
+ if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
+ &period, &slice, &latency, &xtratime) )
+ return NULL;
+
+ if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
+ latency, xtratime) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_atropos_domain_get(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u32 domid;
+ u64 period, slice, latency;
+ int xtratime;
+
+ static char *kwd_list[] = { "dom", NULL };
+
+ if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
+ return NULL;
+
+ if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
+ &slice, &latency, &xtratime ) )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
+ "domain", domid,
+ "period", period,
+ "slice", slice,
+ "latency", latency,
+ "xtratime", xtratime);
+}
+
+
+static PyObject *pyxc_rrobin_global_set(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u64 slice;
+
+ static char *kwd_list[] = { "slice", NULL };
+
+ if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
+ return NULL;
+
+ if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_shadow_control(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ int op=0;
+
+ static char *kwd_list[] = { "dom", "op", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
+ &dom, &op) )
+ return NULL;
+
+ if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_rrobin_global_get(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u64 slice;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:L}", "slice", slice);
+}
+
+static PyObject *pyxc_domain_setname(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ u32 dom;
+ char *name;
+
+ static char *kwd_list[] = { "dom", "name", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
+ &dom, &name) )
+ return NULL;
+
+ if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_setmaxmem(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ unsigned long max_memkb;
+
+ static char *kwd_list[] = { "dom", "max_memkb", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
+ &dom, &max_memkb) )
+ return NULL;
+
+ if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+
+static PyMethodDef pyxc_methods[] = {
+ { "domain_create",
+ (PyCFunction)pyxc_domain_create,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Create a new domain.\n"
+ " mem_kb [int, 0]: Memory allocation, in kilobytes.\n"
+ " name [str, '(anon)']: Informative textual name.\n\n"
+ "Returns: [int] new domain identifier; -1 on error.\n" },
+
+ { "domain_pause",
+ (PyCFunction)pyxc_domain_pause,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Temporarily pause execution of a domain.\n"
+ " dom [int]: Identifier of domain to be paused.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_unpause",
+ (PyCFunction)pyxc_domain_unpause,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "(Re)start execution of a domain.\n"
+ " dom [int]: Identifier of domain to be unpaused.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_destroy",
+ (PyCFunction)pyxc_domain_destroy,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Destroy a domain.\n"
+ " dom [int]: Identifier of domain to be destroyed.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_pincpu",
+ (PyCFunction)pyxc_domain_pincpu,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Pin a domain to a specified CPU.\n"
+ " dom [int]: Identifier of domain to be pinned.\n"
+ " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_getinfo",
+ (PyCFunction)pyxc_domain_getinfo,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Get information regarding a set of domains, in increasing id order.\n"
+ " first_dom [int, 0]: First domain to retrieve info about.\n"
+ " max_doms [int, 1024]: Maximum number of domains to retrieve info"
+ " about.\n\n"
+ "Returns: [list of dicts] if list length is less than 'max_doms'\n"
+ " parameter then there was an error, or the end of the\n"
+ " domain-id space was reached.\n"
+ " dom [int]: Identifier of domain to which this info pertains\n"
+ " cpu [int]: CPU to which this domain is bound\n"
+ " dying [int]: Bool - is the domain dying?\n"
+ " crashed [int]: Bool - has the domain crashed?\n"
+ " shutdown [int]: Bool - has the domain shut itself down?\n"
+ " paused [int]: Bool - is the domain paused by control software?\n"
+ " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
+ " running [int]: Bool - is the domain currently running?\n"
+ " mem_kb [int]: Memory reservation, in kilobytes\n"
+ " cpu_time [long]: CPU time consumed, in nanoseconds\n"
+ " name [str]: Identifying name\n"
+ " shutdown_reason [int]: Numeric code from guest OS, explaining "
+ "reason why it shut itself down.\n" },
+
+ { "linux_save",
+ (PyCFunction)pyxc_linux_save,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Save the CPU and memory state of a Linux guest OS.\n"
+ " dom [int]: Identifier of domain to be saved.\n"
+ " state_file [str]: Name of state file. Must not currently exist.\n"
+ " progress [int, 1]: Bool - display a running progress indication?\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "linux_restore",
+ (PyCFunction)pyxc_linux_restore,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Restore the CPU and memory state of a Linux guest OS.\n"
+ " state_file [str]: Name of state file. Must not currently exist.\n"
+ " progress [int, 1]: Bool - display a running progress indication?\n\n"
+ "Returns: [int] new domain identifier on success; -1 on error.\n" },
+
+ { "linux_build",
+ (PyCFunction)pyxc_linux_build,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Build a new Linux guest OS.\n"
+ " dom [int]: Identifier of domain to build into.\n"
+ " image [str]: Name of kernel image file. May be gzipped.\n"
+ " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
+ " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "netbsd_build",
+ (PyCFunction)pyxc_netbsd_build,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Build a new NetBSD guest OS.\n"
+ " dom [int]: Identifier of domain to build into.\n"
+ " image [str]: Name of kernel image file. May be gzipped.\n"
+ " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "bvtsched_global_set",
+ (PyCFunction)pyxc_bvtsched_global_set,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
+ " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "bvtsched_global_get",
+ (PyCFunction)pyxc_bvtsched_global_get,
+ METH_KEYWORDS, "\n"
+ "Get global tuning parameters for BVT scheduler.\n"
+ "Returns: [dict]:\n"
+ " ctx_allow [int]: context switch allowance\n" },
+
+ { "bvtsched_domain_set",
+ (PyCFunction)pyxc_bvtsched_domain_set,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
+ " dom [int]: Identifier of domain to be tuned.\n"
+ " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
+ " warp [int]: How far to warp domain's EVT on unblock.\n"
+ " warpl [int]: How long the domain can run warped.\n"
+ " warpu [int]: How long before the domain can warp again.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "bvtsched_domain_get",
+ (PyCFunction)pyxc_bvtsched_domain_get,
+ METH_KEYWORDS, "\n"
+ "Get per-domain tuning parameters under the BVT scheduler.\n"
+ " dom [int]: Identifier of domain to be queried.\n"
+ "Returns [dict]:\n"
+ " domain [int]: Domain ID.\n"
+ " mcuadv [long]: MCU Advance.\n"
+ " warp [long]: Warp.\n"
+ " warpu [long]: Unwarp requirement.\n"
+ " warpl [long]: Warp limit,\n"
+ },
+
+ { "atropos_domain_set",
+ (PyCFunction)pyxc_atropos_domain_set,
+ METH_KEYWORDS, "\n"
+ "Set the scheduling parameters for a domain when running with Atropos.\n"
+ " dom [int]: domain to set\n"
+ " period [long]: domain's scheduling period\n"
+ " slice [long]: domain's slice per period\n"
+ " latency [long]: wakeup latency hint\n"
+ " xtratime [int]: boolean\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "atropos_domain_get",
+ (PyCFunction)pyxc_atropos_domain_get,
+ METH_KEYWORDS, "\n"
+ "Get the current scheduling parameters for a domain when running with\n"
+ "the Atropos scheduler."
+ " dom [int]: domain to query\n"
+ "Returns: [dict]\n"
+ " domain [int]: domain ID\n"
+ " period [long]: scheduler period\n"
+ " slice [long]: CPU reservation per period\n"
+ " latency [long]: unblocking latency hint\n"
+ " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
+
+ { "rrobin_global_set",
+ (PyCFunction)pyxc_rrobin_global_set,
+ METH_KEYWORDS, "\n"
+ "Set Round Robin scheduler slice.\n"
+ " slice [long]: Round Robin scheduler slice\n"
+ "Returns: [int] 0 on success, throws an exception on failure\n" },
+
+ { "rrobin_global_get",
+ (PyCFunction)pyxc_rrobin_global_get,
+ METH_KEYWORDS, "\n"
+ "Get Round Robin scheduler settings\n"
+ "Returns [dict]:\n"
+ " slice [long]: Scheduler time slice.\n" },
+
+ { "evtchn_bind_interdomain",
+ (PyCFunction)pyxc_evtchn_bind_interdomain,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Open an event channel between two domains.\n"
+ " dom1 [int, SELF]: First domain to be connected.\n"
+ " dom2 [int, SELF]: Second domain to be connected.\n\n"
+ "Returns: [dict] dictionary is empty on failure.\n"
+ " port1 [int]: Port-id for endpoint at dom1.\n"
+ " port2 [int]: Port-id for endpoint at dom2.\n" },
+
+ { "evtchn_bind_virq",
+ (PyCFunction)pyxc_evtchn_bind_virq,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Bind an event channel to the specified VIRQ.\n"
+ " virq [int]: VIRQ to bind.\n\n"
+ "Returns: [int] Bound event-channel port.\n" },
+
+ { "evtchn_close",
+ (PyCFunction)pyxc_evtchn_close,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Close an event channel.\n"
+ " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
+ " port [int]: Port-id of one endpoint of the channel.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "evtchn_send",
+ (PyCFunction)pyxc_evtchn_send,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Send an event along a locally-connected event channel.\n"
+ " port [int]: Port-id of a local channel endpoint.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "evtchn_status",
+ (PyCFunction)pyxc_evtchn_status,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Query the status of an event channel.\n"
+ " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
+ " port [int]: Port-id of one endpoint of the channel.\n\n"
+ "Returns: [dict] dictionary is empty on failure.\n"
+ " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
+ " or 'virq'.\n"
+ "The following are returned if 'status' is 'interdomain':\n"
+ " dom [int]: Dom-id of remote endpoint.\n"
+ " port [int]: Port-id of remote endpoint.\n"
+ "The following are returned if 'status' is 'pirq' or 'virq':\n"
+ " irq [int]: IRQ number.\n" },
+
+ { "physdev_pci_access_modify",
+ (PyCFunction)pyxc_physdev_pci_access_modify,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Allow a domain access to a PCI device\n"
+ " dom [int]: Identifier of domain to be allowed access.\n"
+ " bus [int]: PCI bus\n"
+ " dev [int]: PCI slot\n"
+ " func [int]: PCI function\n"
+ " enable [int]: Non-zero means enable access; else disable access\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "readconsolering",
+ (PyCFunction)pyxc_readconsolering,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Read Xen's console ring.\n"
+ " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
+ "Returns: [str] string is empty on failure.\n" },
+
+ { "physinfo",
+ (PyCFunction)pyxc_physinfo,
+ METH_VARARGS, "\n"
+ "Get information about the physical host machine\n"
+ "Returns [dict]: information about the hardware"
+ " [None]: on failure.\n" },
+
+ { "shadow_control",
+ (PyCFunction)pyxc_shadow_control,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Set parameter for shadow pagetable interface\n"
+ " dom [int]: Identifier of domain.\n"
+ " op [int, 0]: operation\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_setname",
+ (PyCFunction)pyxc_domain_setname,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Set domain informative textual name\n"
+ " dom [int]: Identifier of domain.\n"
+ " name [str]: Text string.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_setmaxmem",
+ (PyCFunction)pyxc_domain_setmaxmem,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Set a domain's memory limit\n"
+ " dom [int]: Identifier of domain.\n"
+ " max_memkb [long]: .\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+
+/*
+ * Definitions for the 'Xc' module wrapper.
+ */
+
+staticforward PyTypeObject PyXcType;
+
+static PyObject *PyXc_new(PyObject *self, PyObject *args)
+{
+ XcObject *xc;
+
+ if ( !PyArg_ParseTuple(args, ":new") )
+ return NULL;
+
+ xc = PyObject_New(XcObject, &PyXcType);
+
+ if ( (xc->xc_handle = xc_interface_open()) == -1 )
+ {
+ PyObject_Del((PyObject *)xc);
+ return PyErr_SetFromErrno(xc_error);
+ }
+
+ return (PyObject *)xc;
+}
+
+static PyObject *PyXc_getattr(PyObject *obj, char *name)
+{
+ return Py_FindMethod(pyxc_methods, obj, name);
+}
+
+static void PyXc_dealloc(PyObject *self)
+{
+ XcObject *xc = (XcObject *)self;
+ (void)xc_interface_close(xc->xc_handle);
+ PyObject_Del(self);
+}
+
+static PyTypeObject PyXcType = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "Xc",
+ sizeof(XcObject),
+ 0,
+ PyXc_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ PyXc_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+static PyMethodDef PyXc_methods[] = {
+ { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
+ { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxc(void)
+{
+ PyObject *m, *d;
+
+ m = Py_InitModule(XENPKG, PyXc_methods);
+
+ d = PyModule_GetDict(m);
+ xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
+ PyDict_SetItemString(d, "error", xc_error);
+
+ zero = PyInt_FromLong(0);
+}
--- /dev/null
+/******************************************************************************
+ * domain_controller.h
+ *
+ * Interface to server controller (e.g., 'xend'). This header file defines the
+ * interface that is shared with guest OSes.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __DOMAIN_CONTROLLER_H__
+#define __DOMAIN_CONTROLLER_H__
+
+
+#ifndef BASIC_START_INFO
+#error "Xen header file hypervisor-if.h must already be included here."
+#endif
+
+
+/*
+ * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
+ */
+
+typedef struct {
+ BASIC_START_INFO;
+ u16 domain_controller_evtchn; /* 320 */
+} PACKED extended_start_info_t; /* 322 bytes */
+#define SIF_BLK_BE_DOMAIN (1<<4) /* Is this a block backend domain? */
+#define SIF_NET_BE_DOMAIN (1<<5) /* Is this a net backend domain? */
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
+ * interpreted by control software to determine the appropriate action. These
+ * are only really advisories: the controller can actually do as it likes.
+ */
+#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
+#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
+
+
+/*
+ * CONTROLLER MESSAGING INTERFACE.
+ */
+
+typedef struct {
+ u8 type; /* 0: echoed in response */
+ u8 subtype; /* 1: echoed in response */
+ u8 id; /* 2: echoed in response */
+ u8 length; /* 3: number of bytes in 'msg' */
+ u8 msg[60]; /* 4: type-specific message data */
+} PACKED control_msg_t; /* 64 bytes */
+
+#define CONTROL_RING_SIZE 8
+typedef u32 CONTROL_RING_IDX;
+#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
+
+typedef struct {
+ control_msg_t tx_ring[CONTROL_RING_SIZE]; /* 0: guest -> controller */
+ control_msg_t rx_ring[CONTROL_RING_SIZE]; /* 512: controller -> guest */
+ CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
+ CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
+} PACKED control_if_t; /* 1040 bytes */
+
+/*
+ * Top-level command types.
+ */
+#define CMSG_CONSOLE 0 /* Console */
+#define CMSG_BLKIF_BE 1 /* Block-device backend */
+#define CMSG_BLKIF_FE 2 /* Block-device frontend */
+#define CMSG_NETIF_BE 3 /* Network-device backend */
+#define CMSG_NETIF_FE 4 /* Network-device frontend */
+#define CMSG_SHUTDOWN 6 /* Shutdown messages */
+
+
+/******************************************************************************
+ * CONSOLE DEFINITIONS
+ */
+
+/*
+ * Subtypes for console messages.
+ */
+#define CMSG_CONSOLE_DATA 0
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED 0
+
+/* Messages from guest to domain controller. */
+#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED 32
+#define CMSG_BLKIF_FE_INTERFACE_CONNECT 33
+#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT 34
+
+/* These are used by both front-end and back-end drivers. */
+#define blkif_vdev_t u16
+#define blkif_pdev_t u16
+#define blkif_sector_t u64
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ * Notify a guest about a status change on one of its block interfaces.
+ * If the interface is DESTROYED or DOWN then the interface is disconnected:
+ * 1. The shared-memory frame is available for reuse.
+ * 2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
+#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
+typedef struct {
+ u32 handle; /* 0 */
+ u32 status; /* 4 */
+ u16 evtchn; /* 8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
+
+/*
+ * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ * Notify the domain controller that the front-end driver is DOWN or UP.
+ * When the driver goes DOWN then the controller will send no more
+ * status-change notifications. When the driver comes UP then the controller
+ * will send a notification for each interface that currently exists.
+ * If the driver goes DOWN while interfaces are still UP, the domain
+ * will automatically take the interfaces DOWN.
+ */
+#define BLKIF_DRIVER_STATUS_DOWN 0
+#define BLKIF_DRIVER_STATUS_UP 1
+typedef struct {
+ /* IN */
+ u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */
+ /* OUT */
+ /*
+ * Tells driver how many interfaces it should expect to immediately
+ * receive notifications about.
+ */
+ u32 nr_interfaces; /* 4 */
+} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_CONNECT:
+ * If successful, the domain controller will acknowledge with a
+ * STATUS_CONNECTED message.
+ */
+typedef struct {
+ u32 handle; /* 0 */
+ u32 __pad;
+ memory_t shmem_frame; /* 8 */
+ MEMORY_PADDING;
+} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ * If successful, the domain controller will acknowledge with a
+ * STATUS_DISCONNECTED message.
+ */
+typedef struct {
+ u32 handle; /* 0 */
+} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_BLKIF_BE_CREATE 0 /* Create a new block-device interface. */
+#define CMSG_BLKIF_BE_DESTROY 1 /* Destroy a block-device interface. */
+#define CMSG_BLKIF_BE_CONNECT 2 /* Connect i/f to remote driver. */
+#define CMSG_BLKIF_BE_DISCONNECT 3 /* Disconnect i/f from remote driver. */
+#define CMSG_BLKIF_BE_VBD_CREATE 4 /* Create a new VBD for an interface. */
+#define CMSG_BLKIF_BE_VBD_DESTROY 5 /* Delete a VBD from an interface. */
+#define CMSG_BLKIF_BE_VBD_GROW 6 /* Append an extent to a given VBD. */
+#define CMSG_BLKIF_BE_VBD_SHRINK 7 /* Remove last extent from a given VBD. */
+
+/* Messages to domain controller. */
+#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for block-device messages.
+ */
+
+typedef struct {
+ blkif_sector_t sector_start; /* 0 */
+ blkif_sector_t sector_length; /* 8 */
+ blkif_pdev_t device; /* 16 */
+ u16 __pad; /* 18 */
+} PACKED blkif_extent_t; /* 20 bytes */
+
+/* Non-specific 'okay' return. */
+#define BLKIF_BE_STATUS_OKAY 0
+/* Non-specific 'error' return. */
+#define BLKIF_BE_STATUS_ERROR 1
+/* The following are specific error returns. */
+#define BLKIF_BE_STATUS_INTERFACE_EXISTS 2
+#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define BLKIF_BE_STATUS_VBD_EXISTS 5
+#define BLKIF_BE_STATUS_VBD_NOT_FOUND 6
+#define BLKIF_BE_STATUS_OUT_OF_MEMORY 7
+#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND 8
+#define BLKIF_BE_STATUS_MAPPING_ERROR 9
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define BLKIF_BE_STATUS_ERRORS { \
+ "Okay", \
+ "Non-specific error", \
+ "Interface already exists", \
+ "Interface not found", \
+ "Interface is still connected", \
+ "VBD already exists", \
+ "VBD not found", \
+ "Out of memory", \
+ "Extent not found for VBD", \
+ "Could not map domain memory" }
+
+/*
+ * CMSG_BLKIF_BE_CREATE:
+ * When the driver sends a successful response then the interface is fully
+ * created. The controller will send a DOWN notification to the front-end
+ * driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 blkif_handle; /* 4: Domain-specific interface handle. */
+ /* OUT */
+ u32 status; /* 8 */
+} PACKED blkif_be_create_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DESTROY:
+ * When the driver sends a successful response then the interface is fully
+ * torn down. The controller will send a DESTROYED notification to the
+ * front-end driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify interface to be destroyed. */
+ u32 blkif_handle; /* 4: ...ditto... */
+ /* OUT */
+ u32 status; /* 8 */
+} PACKED blkif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_CONNECT:
+ * When the driver sends a successful response then the interface is fully
+ * connected. The controller will send a CONNECTED notification to the
+ * front-end driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 blkif_handle; /* 4: Domain-specific interface handle. */
+ memory_t shmem_frame; /* 8: Page cont. shared comms window. */
+ MEMORY_PADDING;
+ u32 evtchn; /* 16: Event channel for notifications. */
+ /* OUT */
+ u32 status; /* 20 */
+} PACKED blkif_be_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DISCONNECT:
+ * When the driver sends a successful response then the interface is fully
+ * disconnected. The controller will send a DOWN notification to the front-end
+ * driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 blkif_handle; /* 4: Domain-specific interface handle. */
+ /* OUT */
+ u32 status; /* 8 */
+} PACKED blkif_be_disconnect_t; /* 12 bytes */
+
+/* CMSG_BLKIF_BE_VBD_CREATE */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify blkdev interface. */
+ u32 blkif_handle; /* 4: ...ditto... */
+ blkif_vdev_t vdevice; /* 8: Interface-specific id for this VBD. */
+ u16 readonly; /* 10: Non-zero -> VBD isn't writeable. */
+ /* OUT */
+ u32 status; /* 12 */
+} PACKED blkif_be_vbd_create_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_DESTROY */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify blkdev interface. */
+ u32 blkif_handle; /* 4: ...ditto... */
+ blkif_vdev_t vdevice; /* 8: Interface-specific id of the VBD. */
+ u16 __pad; /* 10 */
+ /* OUT */
+ u32 status; /* 12 */
+} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_GROW */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify blkdev interface. */
+ u32 blkif_handle; /* 4: ...ditto... */
+ blkif_extent_t extent; /* 8: Physical extent to append to VBD. */
+ blkif_vdev_t vdevice; /* 28: Interface-specific id of the VBD. */
+ u16 __pad; /* 30 */
+ /* OUT */
+ u32 status; /* 32 */
+} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
+
+/* CMSG_BLKIF_BE_VBD_SHRINK */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify blkdev interface. */
+ u32 blkif_handle; /* 4: ...ditto... */
+ blkif_vdev_t vdevice; /* 8: Interface-specific id of the VBD. */
+ u16 __pad; /* 10 */
+ /* OUT */
+ u32 status; /* 12 */
+} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ * Notify the domain controller that the back-end driver is DOWN or UP.
+ * If the driver goes DOWN while interfaces are still UP, the controller
+ * will automatically send DOWN notifications.
+ */
+typedef struct {
+ u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */
+} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED 0
+
+/* Messages from guest to domain controller. */
+#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED 32
+#define CMSG_NETIF_FE_INTERFACE_CONNECT 33
+#define CMSG_NETIF_FE_INTERFACE_DISCONNECT 34
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ * Notify a guest about a status change on one of its network interfaces.
+ * If the interface is DESTROYED or DOWN then the interface is disconnected:
+ * 1. The shared-memory frame is available for reuse.
+ * 2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
+#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
+typedef struct {
+ u32 handle; /* 0 */
+ u32 status; /* 4 */
+ u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+ u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
+
+/*
+ * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ * Notify the domain controller that the front-end driver is DOWN or UP.
+ * When the driver goes DOWN then the controller will send no more
+ * status-change notifications. When the driver comes UP then the controller
+ * will send a notification for each interface that currently exists.
+ * If the driver goes DOWN while interfaces are still UP, the domain
+ * will automatically take the interfaces DOWN.
+ */
+#define NETIF_DRIVER_STATUS_DOWN 0
+#define NETIF_DRIVER_STATUS_UP 1
+typedef struct {
+ /* IN */
+ u32 status; /* 0: NETIF_DRIVER_STATUS_??? */
+ /* OUT */
+ /*
+ * Tells driver how many interfaces it should expect to immediately
+ * receive notifications about.
+ */
+ u32 nr_interfaces; /* 4 */
+} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_CONNECT:
+ * If successful, the domain controller will acknowledge with a
+ * STATUS_CONNECTED message.
+ */
+typedef struct {
+ u32 handle; /* 0 */
+ u32 __pad; /* 4 */
+ memory_t tx_shmem_frame; /* 8 */
+ MEMORY_PADDING;
+ memory_t rx_shmem_frame; /* 16 */
+ MEMORY_PADDING;
+} PACKED netif_fe_interface_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
+ * If successful, the domain controller will acknowledge with a
+ * STATUS_DISCONNECTED message.
+ */
+typedef struct {
+ u32 handle; /* 0 */
+} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_NETIF_BE_CREATE 0 /* Create a new net-device interface. */
+#define CMSG_NETIF_BE_DESTROY 1 /* Destroy a net-device interface. */
+#define CMSG_NETIF_BE_CONNECT 2 /* Connect i/f to remote driver. */
+#define CMSG_NETIF_BE_DISCONNECT 3 /* Disconnect i/f from remote driver. */
+
+/* Messages to domain controller. */
+#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for net-device messages.
+ */
+
+/* Non-specific 'okay' return. */
+#define NETIF_BE_STATUS_OKAY 0
+/* Non-specific 'error' return. */
+#define NETIF_BE_STATUS_ERROR 1
+/* The following are specific error returns. */
+#define NETIF_BE_STATUS_INTERFACE_EXISTS 2
+#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define NETIF_BE_STATUS_OUT_OF_MEMORY 5
+#define NETIF_BE_STATUS_MAPPING_ERROR 6
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define NETIF_BE_STATUS_ERRORS { \
+ "Okay", \
+ "Non-specific error", \
+ "Interface already exists", \
+ "Interface not found", \
+ "Interface is still connected", \
+ "Out of memory", \
+ "Could not map domain memory" }
+
+/*
+ * CMSG_NETIF_BE_CREATE:
+ * When the driver sends a successful response then the interface is fully
+ * created. The controller will send a DOWN notification to the front-end
+ * driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 netif_handle; /* 4: Domain-specific interface handle. */
+ u8 mac[6]; /* 8 */
+ u16 __pad; /* 14 */
+ /* OUT */
+ u32 status; /* 16 */
+} PACKED netif_be_create_t; /* 20 bytes */
+
+/*
+ * CMSG_NETIF_BE_DESTROY:
+ * When the driver sends a successful response then the interface is fully
+ * torn down. The controller will send a DESTROYED notification to the
+ * front-end driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Identify interface to be destroyed. */
+ u32 netif_handle; /* 4: ...ditto... */
+ /* OUT */
+ u32 status; /* 8 */
+} PACKED netif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_CONNECT:
+ * When the driver sends a successful response then the interface is fully
+ * connected. The controller will send a CONNECTED notification to the
+ * front-end driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 netif_handle; /* 4: Domain-specific interface handle. */
+ memory_t tx_shmem_frame; /* 8: Page cont. tx shared comms window. */
+ MEMORY_PADDING;
+ memory_t rx_shmem_frame; /* 16: Page cont. rx shared comms window. */
+ MEMORY_PADDING;
+ u16 evtchn; /* 24: Event channel for notifications. */
+ u16 __pad; /* 26 */
+ /* OUT */
+ u32 status; /* 28 */
+} PACKED netif_be_connect_t; /* 32 bytes */
+
+/*
+ * CMSG_NETIF_BE_DISCONNECT:
+ * When the driver sends a successful response then the interface is fully
+ * disconnected. The controller will send a DOWN notification to the front-end
+ * driver.
+ */
+typedef struct {
+ /* IN */
+ domid_t domid; /* 0: Domain attached to new interface. */
+ u32 netif_handle; /* 4: Domain-specific interface handle. */
+ /* OUT */
+ u32 status; /* 8 */
+} PACKED netif_be_disconnect_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ * Notify the domain controller that the back-end driver is DOWN or UP.
+ * If the driver goes DOWN while interfaces are still UP, the domain
+ * will automatically send DOWN notifications.
+ */
+typedef struct {
+ u32 status; /* 0: NETIF_DRIVER_STATUS_??? */
+} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * SHUTDOWN DEFINITIONS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_SHUTDOWN_POWEROFF 0 /* Clean shutdown (SHUTDOWN_poweroff). */
+#define CMSG_SHUTDOWN_REBOOT 1 /* Clean shutdown (SHUTDOWN_reboot). */
+#define CMSG_SHUTDOWN_SUSPEND 2 /* Create suspend info, then */
+ /* SHUTDOWN_suspend. */
+
+#endif /* __DOMAIN_CONTROLLER_H__ */
--- /dev/null
+/******************************************************************************
+ * utils.c
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+
+#include <hypervisor-if.h>
+#include "domain_controller.h"
+
+#include <asm-xen/proc_cmd.h>
+
+#define XENPKG "xen.lowlevel.xu"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL 0x0000 /* A standard event notification. */
+#define PORT_EXCEPTION 0x8000 /* An exceptional notification. */
+#define PORTIDX_MASK 0x7fff /* Strip subtype to obtain port index. */
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+ PyObject_HEAD;
+ int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ u16 v;
+ int bytes;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ if ( errno == EAGAIN )
+ goto none;
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ if ( bytes == sizeof(v) )
+ return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ u16 v;
+ int idx;
+
+ if ( !PyArg_ParseTuple(args, "i", &idx) )
+ return NULL;
+
+ v = (u16)idx;
+
+ (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ int idx;
+
+ if ( !PyArg_ParseTuple(args, "i", &idx) )
+ return NULL;
+
+ if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ int idx;
+
+ if ( !PyArg_ParseTuple(args, "i", &idx) )
+ return NULL;
+
+ if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+ { "read",
+ (PyCFunction)xu_notifier_read,
+ METH_VARARGS,
+ "Read a (@port, @type) pair.\n" },
+
+ { "unmask",
+ (PyCFunction)xu_notifier_unmask,
+ METH_VARARGS,
+ "Unmask notifications for a @port.\n" },
+
+ { "bind",
+ (PyCFunction)xu_notifier_bind,
+ METH_VARARGS,
+ "Get notifications for a @port.\n" },
+
+ { "unbind",
+ (PyCFunction)xu_notifier_unbind,
+ METH_VARARGS,
+ "No longer get notifications for a @port.\n" },
+
+ { "fileno",
+ (PyCFunction)xu_notifier_fileno,
+ METH_VARARGS,
+ "Return the file descriptor for the notification channel.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ reopen:
+ xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+ if ( xun->evtchn_fd == -1 )
+ {
+ if ( (errno == ENOENT) &&
+ ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+ (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
+ (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
+ goto reopen;
+ PyObject_Del((PyObject *)xun);
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+ if ( strcmp(name, "EXCEPTION") == 0 )
+ return PyInt_FromLong(PORT_EXCEPTION);
+ if ( strcmp(name, "NORMAL") == 0 )
+ return PyInt_FromLong(PORT_NORMAL);
+ return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ (void)close(xun->evtchn_fd);
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "notifier",
+ sizeof(xu_notifier_object),
+ 0,
+ xu_notifier_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_notifier_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+#define TYPE(_x,_y) (((_x)<<8)|(_y))
+#define P2C(_struct, _field, _ctype) \
+ do { \
+ PyObject *obj; \
+ if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
+ { \
+ if ( PyInt_Check(obj) ) \
+ { \
+ ((_struct *)&xum->msg.msg[0])->_field = \
+ (_ctype)PyInt_AsLong(obj); \
+ dict_items_parsed++; \
+ } \
+ else if ( PyLong_Check(obj) ) \
+ { \
+ ((_struct *)&xum->msg.msg[0])->_field = \
+ (_ctype)PyLong_AsUnsignedLongLong(obj); \
+ dict_items_parsed++; \
+ } \
+ } \
+ xum->msg.length = sizeof(_struct); \
+ } while ( 0 )
+#define C2P(_struct, _field, _pytype, _ctype) \
+ do { \
+ PyObject *obj = Py ## _pytype ## _From ## _ctype \
+ (((_struct *)&xum->msg.msg[0])->_field); \
+ if ( dict == NULL ) dict = PyDict_New(); \
+ PyDict_SetItemString(dict, #_field, obj); \
+ } while ( 0 )
+
+typedef struct {
+ PyObject_HEAD;
+ control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+ char *str;
+ int len;
+
+ if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+ return NULL;
+
+ if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+ {
+ PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+ return NULL;
+ }
+
+ memcpy(&xum->msg.msg[xum->msg.length], str, len);
+ xum->msg.length += len;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+ PyObject *payload;
+ int dict_items_parsed = 0;
+
+ if ( !PyArg_ParseTuple(args, "O", &payload) )
+ return NULL;
+
+ if ( !PyDict_Check(payload) )
+ {
+ PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+ return NULL;
+ }
+
+ switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+ {
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+ P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+ break;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+ P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+ break;
+ }
+
+ if ( dict_items_parsed != PyDict_Size(payload) )
+ {
+ PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+ PyObject *dict = NULL;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+ {
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+ C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
+ C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
+ C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+ C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
+ C2P(blkif_fe_interface_connect_t, handle, Int, Long);
+ C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
+ C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+ C2P(blkif_be_create_t, domid, Int, Long);
+ C2P(blkif_be_create_t, blkif_handle, Int, Long);
+ C2P(blkif_be_create_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+ C2P(blkif_be_destroy_t, domid, Int, Long);
+ C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
+ C2P(blkif_be_destroy_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+ C2P(blkif_be_connect_t, domid, Int, Long);
+ C2P(blkif_be_connect_t, blkif_handle, Int, Long);
+ C2P(blkif_be_connect_t, shmem_frame, Int, Long);
+ C2P(blkif_be_connect_t, evtchn, Int, Long);
+ C2P(blkif_be_connect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+ C2P(blkif_be_disconnect_t, domid, Int, Long);
+ C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
+ C2P(blkif_be_disconnect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+ C2P(blkif_be_vbd_create_t, domid, Int, Long);
+ C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
+ C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
+ C2P(blkif_be_vbd_create_t, readonly, Int, Long);
+ C2P(blkif_be_vbd_create_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+ C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
+ C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
+ C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
+ C2P(blkif_be_vbd_destroy_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+ C2P(blkif_be_vbd_grow_t, domid, Int, Long);
+ C2P(blkif_be_vbd_grow_t, blkif_handle, Int, Long);
+ C2P(blkif_be_vbd_grow_t, vdevice, Int, Long);
+ C2P(blkif_be_vbd_grow_t, extent.sector_start,
+ Long, UnsignedLongLong);
+ C2P(blkif_be_vbd_grow_t, extent.sector_length,
+ Long, UnsignedLongLong);
+ C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
+ C2P(blkif_be_vbd_grow_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+ C2P(blkif_be_vbd_shrink_t, domid, Int, Long);
+ C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
+ C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long);
+ C2P(blkif_be_vbd_shrink_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
+ C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+ C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
+ C2P(netif_fe_interface_status_changed_t, status, Int, Long);
+ C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+ C2P(netif_fe_driver_status_changed_t, status, Int, Long);
+ C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
+ C2P(netif_fe_interface_connect_t, handle, Int, Long);
+ C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
+ C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
+ C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+ C2P(netif_be_create_t, domid, Int, Long);
+ C2P(netif_be_create_t, netif_handle, Int, Long);
+ C2P(netif_be_create_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+ C2P(netif_be_destroy_t, domid, Int, Long);
+ C2P(netif_be_destroy_t, netif_handle, Int, Long);
+ C2P(netif_be_destroy_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+ C2P(netif_be_connect_t, domid, Int, Long);
+ C2P(netif_be_connect_t, netif_handle, Int, Long);
+ C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
+ C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
+ C2P(netif_be_connect_t, evtchn, Int, Long);
+ C2P(netif_be_connect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+ C2P(netif_be_disconnect_t, domid, Int, Long);
+ C2P(netif_be_disconnect_t, netif_handle, Int, Long);
+ C2P(netif_be_disconnect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
+ C2P(netif_be_driver_status_changed_t, status, Int, Long);
+ return dict;
+ }
+
+ return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ return Py_BuildValue("{s:i,s:i,s:i}",
+ "type", xum->msg.type,
+ "subtype", xum->msg.subtype,
+ "id", xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+ { "append_payload",
+ (PyCFunction)xu_message_append_payload,
+ METH_VARARGS,
+ "Append @str to the message payload.\n" },
+
+ { "set_response_fields",
+ (PyCFunction)xu_message_set_response_fields,
+ METH_VARARGS,
+ "Fill in the response fields in a message that was passed to us.\n" },
+
+ { "get_payload",
+ (PyCFunction)xu_message_get_payload,
+ METH_VARARGS,
+ "Return the message payload in string form.\n" },
+
+ { "get_header",
+ (PyCFunction)xu_message_get_header,
+ METH_VARARGS,
+ "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum;
+ int type, subtype, id, dict_items_parsed = 0;
+ PyObject *payload = NULL;
+
+ if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
+ return NULL;
+
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+
+ xum->msg.type = type;
+ xum->msg.subtype = subtype;
+ xum->msg.id = id;
+ xum->msg.length = 0;
+
+ if ( payload == NULL )
+ return (PyObject *)xum;
+
+ if ( !PyDict_Check(payload) )
+ {
+ PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+ PyObject_Del((PyObject *)xum);
+ return NULL;
+ }
+
+ switch ( TYPE(type, subtype) )
+ {
+ case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+ P2C(blkif_fe_interface_status_changed_t, handle, u32);
+ P2C(blkif_fe_interface_status_changed_t, status, u32);
+ P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+ P2C(blkif_be_create_t, domid, u32);
+ P2C(blkif_be_create_t, blkif_handle, u32);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+ P2C(blkif_be_destroy_t, domid, u32);
+ P2C(blkif_be_destroy_t, blkif_handle, u32);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+ P2C(blkif_be_connect_t, domid, u32);
+ P2C(blkif_be_connect_t, blkif_handle, u32);
+ P2C(blkif_be_connect_t, shmem_frame, memory_t);
+ P2C(blkif_be_connect_t, evtchn, u16);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+ P2C(blkif_be_disconnect_t, domid, u32);
+ P2C(blkif_be_disconnect_t, blkif_handle, u32);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+ P2C(blkif_be_vbd_create_t, domid, u32);
+ P2C(blkif_be_vbd_create_t, blkif_handle, u32);
+ P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
+ P2C(blkif_be_vbd_create_t, readonly, u16);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+ P2C(blkif_be_vbd_destroy_t, domid, u32);
+ P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
+ P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+ P2C(blkif_be_vbd_grow_t, domid, u32);
+ P2C(blkif_be_vbd_grow_t, blkif_handle, u32);
+ P2C(blkif_be_vbd_grow_t, vdevice, blkif_vdev_t);
+ P2C(blkif_be_vbd_grow_t, extent.sector_start, blkif_sector_t);
+ P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
+ P2C(blkif_be_vbd_grow_t, extent.device, blkif_pdev_t);
+ break;
+ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+ P2C(blkif_be_vbd_shrink_t, domid, u32);
+ P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
+ P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t);
+ break;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+ P2C(netif_fe_interface_status_changed_t, handle, u32);
+ P2C(netif_fe_interface_status_changed_t, status, u32);
+ P2C(netif_fe_interface_status_changed_t, evtchn, u16);
+ P2C(netif_fe_interface_status_changed_t, mac[0], u8);
+ P2C(netif_fe_interface_status_changed_t, mac[1], u8);
+ P2C(netif_fe_interface_status_changed_t, mac[2], u8);
+ P2C(netif_fe_interface_status_changed_t, mac[3], u8);
+ P2C(netif_fe_interface_status_changed_t, mac[4], u8);
+ P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+ break;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+ P2C(netif_be_create_t, domid, u32);
+ P2C(netif_be_create_t, netif_handle, u32);
+ P2C(netif_be_create_t, mac[0], u8);
+ P2C(netif_be_create_t, mac[1], u8);
+ P2C(netif_be_create_t, mac[2], u8);
+ P2C(netif_be_create_t, mac[3], u8);
+ P2C(netif_be_create_t, mac[4], u8);
+ P2C(netif_be_create_t, mac[5], u8);
+ break;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+ P2C(netif_be_destroy_t, domid, u32);
+ P2C(netif_be_destroy_t, netif_handle, u32);
+ break;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+ P2C(netif_be_connect_t, domid, u32);
+ P2C(netif_be_connect_t, netif_handle, u32);
+ P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
+ P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
+ P2C(netif_be_connect_t, evtchn, u16);
+ break;
+ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+ P2C(netif_be_disconnect_t, domid, u32);
+ P2C(netif_be_disconnect_t, netif_handle, u32);
+ break;
+ case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+ P2C(netif_fe_driver_status_changed_t, status, u32);
+ P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+ break;
+ }
+
+ if ( dict_items_parsed != PyDict_Size(payload) )
+ {
+ PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+ PyObject_Del((PyObject *)xum);
+ return NULL;
+ }
+
+ return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+ xu_message_object *xum;
+ if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+ return PyInt_FromLong(sizeof(xum->msg.msg));
+ return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "message",
+ sizeof(xu_message_object),
+ 0,
+ xu_message_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_message_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+ char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, pfn * PAGE_SIZE);
+ if ( vaddr == MAP_FAILED )
+ return NULL;
+ return (control_if_t *)(vaddr + 2048);
+}
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+ char *vaddr = (char *)c - 2048;
+ (void)munmap(vaddr, PAGE_SIZE);
+}
+
+typedef struct xu_port_object {
+ PyObject_HEAD;
+ int mem_fd;
+ int xc_handle;
+ u32 remote_dom;
+ int local_port, remote_port;
+ control_if_t *interface;
+ CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+ CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static int xup_connect(xu_port_object *xup, domid_t dom,
+ int local_port, int remote_port){
+ // From our prespective rx = producer, tx = consumer.
+ int err = 0;
+ printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom,
+ local_port, remote_port);
+
+ // Consumer = tx.
+ //xup->interface->tx_resp_prod = 0;
+ //xup->interface->tx_req_prod = 0;
+ xup->tx_resp_prod = xup->interface->tx_resp_prod;
+ xup->tx_req_cons = xup->interface->tx_resp_prod;
+ printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
+ (unsigned int)xup->interface->tx_resp_prod,
+ (unsigned int)xup->tx_resp_prod,
+ (unsigned int)xup->tx_req_cons,
+ (unsigned int)xup->interface->tx_req_prod);
+
+ // Producer = rx.
+ //xup->interface->rx_req_prod = 0;
+ //xup->interface->rx_resp_prod = 0;
+ xup->rx_req_prod = xup->interface->rx_req_prod;
+ xup->rx_resp_cons = xup->interface->rx_resp_prod;
+ printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
+ (unsigned int)xup->rx_resp_cons,
+ (unsigned int)xup->interface->rx_resp_prod,
+ (unsigned int)xup->interface->rx_req_prod,
+ (unsigned int)xup->rx_req_prod);
+
+ xup->remote_dom = dom;
+ xup->local_port = local_port;
+ xup->remote_port = remote_port;
+
+ printf("%s< err=%d\n", __FUNCTION__, err);
+ return err;
+}
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX c = xup->tx_req_cons;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (c == cif->tx_req_prod) ||
+ ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+ {
+ PyErr_SetString(port_error, "no request to read");
+ return NULL;
+ }
+
+ cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+ memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+ if ( xum->msg.length > sizeof(xum->msg.msg) )
+ xum->msg.length = sizeof(xum->msg.msg);
+ xup->tx_req_cons++;
+ return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX p = xup->rx_req_prod;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+ return NULL;
+
+ if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+ {
+ PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+ return NULL;
+ }
+
+ if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+ {
+ PyErr_SetString(port_error, "no space to write request");
+ return NULL;
+ }
+
+ cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+ memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+ xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX c = xup->rx_resp_cons;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+ {
+ PyErr_SetString(port_error, "no response to read");
+ return NULL;
+ }
+
+ cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+ memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+ if ( xum->msg.length > sizeof(xum->msg.msg) )
+ xum->msg.length = sizeof(xum->msg.msg);
+ xup->rx_resp_cons++;
+ return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX p = xup->tx_resp_prod;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+ return NULL;
+
+ if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+ {
+ PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+ return NULL;
+ }
+
+ if ( p == xup->tx_req_cons )
+ {
+ PyErr_SetString(port_error, "no space to write response");
+ return NULL;
+ }
+
+ cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+ memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+ xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX c = xup->tx_req_cons;
+ control_if_t *cif = xup->interface;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (c == cif->tx_req_prod) ||
+ ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX p = xup->rx_req_prod;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX c = xup->rx_resp_cons;
+ control_if_t *cif = xup->interface;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+ PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX p = xup->tx_resp_prod;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( p == xup->tx_req_cons )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+ { "notify",
+ (PyCFunction)xu_port_notify,
+ METH_VARARGS,
+ "Send a notification to the remote end.\n" },
+
+ { "read_request",
+ (PyCFunction)xu_port_read_request,
+ METH_VARARGS,
+ "Read a request message from the control interface.\n" },
+
+ { "write_request",
+ (PyCFunction)xu_port_write_request,
+ METH_VARARGS,
+ "Write a request message to the control interface.\n" },
+
+ { "read_response",
+ (PyCFunction)xu_port_read_response,
+ METH_VARARGS,
+ "Read a response message from the control interface.\n" },
+
+ { "write_response",
+ (PyCFunction)xu_port_write_response,
+ METH_VARARGS,
+ "Write a response message to the control interface.\n" },
+
+ { "request_to_read",
+ (PyCFunction)xu_port_request_to_read,
+ METH_VARARGS,
+ "Returns TRUE if there is a request message to read.\n" },
+
+ { "space_to_write_request",
+ (PyCFunction)xu_port_space_to_write_request,
+ METH_VARARGS,
+ "Returns TRUE if there is space to write a request message.\n" },
+
+ { "response_to_read",
+ (PyCFunction)xu_port_response_to_read,
+ METH_VARARGS,
+ "Returns TRUE if there is a response message to read.\n" },
+
+ { "space_to_write_response",
+ (PyCFunction)xu_port_space_to_write_response,
+ METH_VARARGS,
+ "Returns TRUE if there is space to write a response message.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup;
+ u32 dom;
+ int port1, port2;
+ xc_dominfo_t info;
+
+ if ( !PyArg_ParseTuple(args, "i", &dom) )
+ return NULL;
+
+ xup = PyObject_New(xu_port_object, &xu_port_type);
+
+ if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+ {
+ PyErr_SetString(port_error, "Could not open '/dev/mem'");
+ goto fail1;
+ }
+
+ /* Set the General-Purpose Subject whose page frame will be mapped. */
+ (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
+
+ if ( (xup->xc_handle = xc_interface_open()) == -1 )
+ {
+ PyErr_SetString(port_error, "Could not open Xen control interface");
+ goto fail2;
+ }
+
+ if ( dom == 0 )
+ {
+ /*
+ * The control-interface event channel for DOM0 is already set up.
+ * We use an ioctl to discover the port at our end of the channel.
+ */
+ port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
+ port2 = -1; /* We don't need the remote end of the DOM0 link. */
+ if ( port1 < 0 )
+ {
+ PyErr_SetString(port_error, "Could not open channel to DOM0");
+ goto fail3;
+ }
+ }
+ else if ( xc_evtchn_bind_interdomain(xup->xc_handle,
+ DOMID_SELF, dom,
+ &port1, &port2) != 0 )
+ {
+ PyErr_SetString(port_error, "Could not open channel to domain");
+ goto fail3;
+ }
+
+ if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+ (info.domid != dom) )
+ {
+ PyErr_SetString(port_error, "Failed to obtain domain status");
+ goto fail4;
+ }
+
+ xup->interface =
+ map_control_interface(xup->mem_fd, info.shared_info_frame);
+ if ( xup->interface == NULL )
+ {
+ PyErr_SetString(port_error, "Failed to map domain control interface");
+ goto fail4;
+ }
+
+ xup_connect(xup, dom, port1, port2);
+ return (PyObject *)xup;
+
+
+ fail4:
+ (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+ (void)xc_interface_close(xup->xc_handle);
+ fail2:
+ (void)close(xup->mem_fd);
+ fail1:
+ PyObject_Del((PyObject *)xup);
+ return NULL;
+}
+
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
+{
+ xu_port_object *xup = (xu_port_object *)obj;
+ if ( strcmp(name, "local_port") == 0 )
+ return PyInt_FromLong(xup->local_port);
+ if ( strcmp(name, "remote_port") == 0 )
+ return PyInt_FromLong(xup->remote_port);
+ if ( strcmp(name, "remote_dom") == 0 )
+ return PyInt_FromLong(xup->remote_dom);
+ return Py_FindMethod(xu_port_methods, obj, name);
+}
+
+static void xu_port_dealloc(PyObject *self)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ unmap_control_interface(xup->mem_fd, xup->interface);
+ if ( xup->remote_dom != 0 )
+ (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+ (void)xc_interface_close(xup->xc_handle);
+ (void)close(xup->mem_fd);
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_port_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "port",
+ sizeof(xu_port_object),
+ 0,
+ xu_port_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_port_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
+
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
+
+typedef struct {
+ PyObject_HEAD;
+ char *buf;
+ unsigned int prod, cons;
+} xu_buffer_object;
+
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+ PyObject *str1, *str2;
+ int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+ len1 = xub->prod - xub->cons;
+ if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+ len1 = BUFSZ - c;
+ if ( len1 > max ) /* clip to specified maximum */
+ len1 = max;
+ if ( len1 < 0 ) /* sanity */
+ len1 = 0;
+
+ if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+ return NULL;
+
+ if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
+ {
+ len2 = max - len1;
+ if ( len2 > MASK_BUF_IDX(xub->prod) )
+ len2 = MASK_BUF_IDX(xub->prod);
+ if ( len2 > 0 )
+ {
+ str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+ if ( str2 == NULL )
+ return NULL;
+ PyString_ConcatAndDel(&str1, str2);
+ if ( str1 == NULL )
+ return NULL;
+ }
+ }
+
+ return str1;
+}
+
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ int max = 1024;
+
+ if ( !PyArg_ParseTuple(args, "|i", &max) )
+ return NULL;
+
+ return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ PyObject *str;
+ int max = 1024;
+
+ if ( !PyArg_ParseTuple(args, "|i", &max) )
+ return NULL;
+
+ if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+ xub->cons += PyString_Size(str);
+
+ return str;
+}
+
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ int max, len;
+
+ if ( !PyArg_ParseTuple(args, "i", &max) )
+ return NULL;
+
+ len = xub->prod - xub->cons;
+ if ( len > max )
+ len = max;
+ if ( len < 0 )
+ len = 0;
+
+ xub->cons += len;
+
+ return PyInt_FromLong(len);
+}
+
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ char *str;
+ int len, len1, len2;
+
+ if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+ return NULL;
+
+ len1 = len;
+ if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+ len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+ if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+ len1 = BUFSZ - (xub->prod - xub->cons);
+
+ if ( len1 == 0 )
+ return PyInt_FromLong(0);
+
+ memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+ xub->prod += len1;
+
+ if ( len1 < len )
+ {
+ len2 = len - len1;
+ if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+ len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+ if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+ len2 = BUFSZ - (xub->prod - xub->cons);
+ if ( len2 != 0 )
+ {
+ memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+ xub->prod += len2;
+ return PyInt_FromLong(len1 + len2);
+ }
+ }
+
+ return PyInt_FromLong(len1);
+}
+
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xub->cons == xub->prod )
+ return PyInt_FromLong(1);
+
+ return PyInt_FromLong(0);
+}
+
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (xub->prod - xub->cons) == BUFSZ )
+ return PyInt_FromLong(1);
+
+ return PyInt_FromLong(0);
+}
+
+static PyMethodDef xu_buffer_methods[] = {
+ { "peek",
+ (PyCFunction)xu_buffer_peek,
+ METH_VARARGS,
+ "Peek up to @max bytes from the buffer. Returns a string.\n" },
+
+ { "read",
+ (PyCFunction)xu_buffer_read,
+ METH_VARARGS,
+ "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+ { "discard",
+ (PyCFunction)xu_buffer_discard,
+ METH_VARARGS,
+ "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+ { "write",
+ (PyCFunction)xu_buffer_write,
+ METH_VARARGS,
+ "Write @string into buffer. Return number of bytes written.\n" },
+
+ { "empty",
+ (PyCFunction)xu_buffer_empty,
+ METH_VARARGS,
+ "Return TRUE if the buffer is empty.\n" },
+
+ { "full",
+ (PyCFunction)xu_buffer_full,
+ METH_VARARGS,
+ "Return TRUE if the buffer is full.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+ if ( (xub->buf = malloc(BUFSZ)) == NULL )
+ {
+ PyObject_Del((PyObject *)xub);
+ return NULL;
+ }
+
+ xub->prod = xub->cons = 0;
+
+ return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+ return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ free(xub->buf);
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_buffer_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "buffer",
+ sizeof(xu_buffer_object),
+ 0,
+ xu_buffer_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_buffer_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
+{
+ while ( waitpid(-1, NULL, WNOHANG) > 0 )
+ continue;
+}
+
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+ struct sigaction sa;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handle_child_death;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+ { "notifier", xu_notifier_new, METH_VARARGS,
+ "Create a new notifier." },
+ { "message", xu_message_new, METH_VARARGS,
+ "Create a new communications message." },
+ { "port", xu_port_new, METH_VARARGS,
+ "Create a new communications port." },
+ { "buffer", xu_buffer_new, METH_VARARGS,
+ "Create a new ring buffer." },
+ { "autoreap", xu_autoreap, METH_VARARGS,
+ "Ensure that zombie children are automatically reaped by the OS." },
+ { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxu(void)
+{
+ PyObject *m, *d;
+
+ m = Py_InitModule(XENPKG, xu_methods);
+
+ d = PyModule_GetDict(m);
+ port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
+ PyDict_SetItemString(d, "PortError", port_error);
+}
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import socket
-import xen.ext.xc
-xc = xen.ext.xc.new()
+import xen.lowlevel.xc
+xc = xen.lowlevel.xc.new()
import sxp
import XendRoot
from twisted.internet import defer
-import xen.ext.xc; xc = xen.ext.xc.new()
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
import sxp
import XendRoot
self.xconsole = XendConsole.instance()
# Table of domain info indexed by domain id.
self.db = XendDB.XendDB(self.dbpath)
- #self.domain = {}
self.domain_db = self.db.fetchall("")
if xroot.get_rebooted():
print 'XendDomain> rebooted: removing all domain info'
self.initial_refresh()
def onVirq(self, event, val):
+ """Event handler for virq.
+ """
print 'XendDomain> virq', val
self.reap()
def _new_domain(self, savedinfo, info):
"""Create a domain entry from saved info.
+
+ savedinfo saved info from the db
+ info domain info from xen
+
+ returns deferred
"""
-## console = None
-## kernel = None
-## id = sxp.child_value(info, 'id')
-## dom = int(id)
-## name = sxp.child_value(info, 'name')
-## memory = int(sxp.child_value(info, 'memory'))
-## consoleinfo = sxp.child(info, 'console')
-## if consoleinfo:
-## consoleid = sxp.child_value(consoleinfo, 'id')
-## console = self.xconsole.console_get(consoleid)
-## if dom and console is None:
-## # Try to connect a console.
-## console = self.xconsole.console_create(dom)
-## config = sxp.child(info, 'config')
-## if config:
-## image = sxp.child(info, 'image')
-## if image:
-## image = sxp.child0(image)
-## kernel = sxp.child_value(image, 'kernel')
-## dominfo = XendDomainInfo.XendDomainInfo(
-## config, dom, name, memory, kernel, console)
config = sxp.child_value(savedinfo, 'config')
deferred = XendDomainInfo.vm_recreate(config, info)
def fn(dominfo):
return deferred
def _add_domain(self, id, info, notify=1):
+ """Add a domain entry to the tables.
+
+ id domain id
+ info domain info object
+ notify send a domain created event if true
+ """
self.domain[id] = info
self.domain_db[id] = info.sxpr()
self.sync_domain(id)
if notify: eserver.inject('xend.domain.created', id)
def _delete_domain(self, id, notify=1):
+ """Remove a domain from the tables.
+
+ id domain id
+ notify send a domain died event if true
+ """
if id in self.domain:
if notify: eserver.inject('xend.domain.died', id)
del self.domain[id]
self.db.delete(id)
def reap(self):
- """Go through the domains looking for ones that have crashed or stopped.
+ """Look for domains that have crashed or stopped.
Tidy them up.
"""
print 'XendDomain>reap>'
domlist = xc.domain_getinfo()
casualties = []
for d in domlist:
- #print 'dom', d
dead = 0
dead = dead or (d['crashed'] or d['shutdown'])
dead = dead or (d['dying'] and
for d in casualties:
id = str(d['dom'])
print 'XendDomain>reap> died id=', id, d
- dominfo = self.domain.get(id)
- if not dominfo: continue
- dominfo.died()
self.domain_destroy(id, refresh=0)
print 'XendDomain>reap<'
doms[id] = d
if id not in self.domain:
config = None
- #image = None
- #newinfo = XendDomainInfo.XendDomainInfo(
- # config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
deferred = XendDomainInfo.vm_recreate(config, d)
def fn(dominfo):
self._add_domain(dominfo.id, dominfo)
self.reap()
def refresh_domain(self, id):
+ """Refresh information for a single domain.
+
+ id domain id
+ """
dom = int(id)
dominfo = xc.domain_getinfo(dom, 1)
if dominfo == [] or dominfo[0]['dom'] != dom:
d.update(dominfo[0])
def domain_ls(self):
- # List domains.
- # Update info from kernel first.
+ """Get list of domain ids.
+
+ return domain ids
+ """
self.refresh()
return self.domain.keys()
def domains(self):
+ """Get list of domain objects.
+
+ return domain objects
+ """
self.refresh()
return self.domain.values()
def domain_create(self, config):
- # Create domain, log it.
+ """Create a domain from a configuration.
+
+ config configuration
+
+ returns deferred
+ """
deferred = XendDomainInfo.vm_create(config)
def fn(dominfo):
self._add_domain(dominfo.id, dominfo)
return deferred
def domain_get(self, id):
+ """Get up-to-date info about a domain.
+
+ id domain id
+ returns domain object (or None)
+ """
id = str(id)
self.refresh_domain(id)
return self.domain.get(id)
def domain_unpause(self, id):
- """(Re)start domain running.
+ """Unpause domain execution.
+
+ id domain id
"""
dom = int(id)
eserver.inject('xend.domain.unpause', id)
def domain_pause(self, id):
"""Pause domain execution.
+
+ id domain id
"""
dom = int(id)
eserver.inject('xend.domain.pause', id)
def domain_shutdown(self, id, reason='poweroff'):
"""Shutdown domain (nicely).
+
+ id domain id
+ reason shutdown type: poweroff, reboot, halt
"""
dom = int(id)
if dom <= 0:
def domain_destroy(self, id, refresh=1):
"""Terminate domain immediately.
+
+ id domain id
+ refresh send a domain destroy event if true
"""
dom = int(id)
if dom <= 0:
return 0
eserver.inject('xend.domain.destroy', id)
- val = xc.domain_destroy(dom=dom)
+ dominfo = self.domain.get(id)
+ if dominfo:
+ val = dominfo.destroy()
+ else:
+ val = xc.domain_destroy(dom=dom)
if refresh: self.refresh()
return val
def domain_migrate(self, id, dst):
"""Start domain migration.
+
+ id domain id
"""
# Need a cancel too?
pass
def domain_save(self, id, dst, progress=0):
- """Save domain state to file, destroy domain.
+ """Save domain state to file, destroy domain on success.
+ Leave domain running on error.
+
+ id domain id
+ dst destination file
+ progress output progress if true
"""
dom = int(id)
dominfo = self.domain_get(id)
vmconfig = sxp.to_string(dominfo.sxpr())
self.domain_pause(id)
eserver.inject('xend.domain.save', id)
- rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress)
+ try:
+ rc = xc.linux_save(dom=dom, state_file=dst,
+ vmconfig=vmconfig, progress=progress)
+ except:
+ rc = -1
if rc == 0:
self.domain_destroy(id)
+ else:
+ self.domain_unpause(id)
return rc
def domain_restore(self, src, progress=0):
"""Restore domain from file.
+
+ src source file
+ progress output progress if true
+
+ returns domain object
"""
dominfo = XendDomainInfo.vm_restore(src, progress=progress)
self._add_domain(dominfo.id, dominfo)
return dominfo
- #============================================================================
- # Backward compatibility stuff from here on.
-
def domain_pincpu(self, dom, cpu):
+ """Pin a domain to a cpu.
+
+ dom domain
+ cpu cpu number
+ """
dom = int(dom)
return xc.domain_pincpu(dom, cpu)
def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+ """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain.
+ """
dom = int(dom)
return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
warp=warp, warpl=warpl, warpu=warpu)
def domain_cpu_bvt_get(self, dom):
+ """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain.
+ """
dom = int(dom)
return xc.bvtsched_domain_get(dom)
def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+ """Set Atropos scheduler parameters for a domain.
+ """
dom = int(dom)
return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
def domain_cpu_atropos_get(self, dom):
+ """Get Atropos scheduler parameters for a domain.
+ """
dom = int(dom)
return xc.atropos_domain_get(dom)
- def domain_vif_ls(self, dom):
+ def domain_devtype_ls(self, dom, type):
+ """Get list of device indexes for a domain.
+
+ dom domain
+ type device type
+
+ returns device indexes
+ """
dominfo = self.domain_get(dom)
if not dominfo: return None
- devs = dominfo.get_devices('vif')
+ devs = dominfo.get_devices(type)
return range(0, len(devs))
- def domain_vif_get(self, dom, vif):
+ def domain_devtype_get(self, dom, type, idx):
+ """Get a device from a domain.
+
+ dom domain
+ type device type
+ idx device index
+
+ returns device object (or None)
+ """
dominfo = self.domain_get(dom)
if not dominfo: return None
- return dominfo.get_device_by_index(vif)
+ return dominfo.get_device_by_index(type, idx)
+
+ def domain_vif_ls(self, dom):
+ """Get list of virtual network interface (vif) indexes for a domain.
+
+ dom domain
+
+ returns vif indexes
+ """
+ return self.domain_devtype_ls(dom, 'vif')
-## def domain_vif_ip_add(self, dom, vif, ip):
-## dom = int(dom)
-## return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
+ def domain_vif_get(self, dom, vif):
+ """Get a virtual network interface (vif) from a domain.
+
+ dom domain
+ vif vif index
+
+ returns vif device object (or None)
+ """
+ return self.domain_devtype_get(dom, 'vif', vif)
def domain_vbd_ls(self, dom):
- dominfo = self.domain_get(dom)
- if not dominfo: return []
- devs = dominfo.get_devices('vbd')
- return [ sxp.child_value(v, 'dev') for v in devs ]
+ """Get list of virtual block device (vbd) indexes for a domain.
+
+ dom domain
+
+ returns vbd indexes
+ """
+ return self.domain_devtype_ls(dom, 'vbd')
def domain_vbd_get(self, dom, vbd):
- dominfo = self.domain_get(dom)
- if not dominfo: return None
- devs = dominfo.get_devices('vbd')
- for v in devs:
- if sxp.child_value(v, 'dev') == vbd:
- return v
- return None
+ """Get a virtual block device (vbd) from a domain.
+
+ dom domain
+ vbd vbd index
+
+ returns vbd device (or None)
+ """
+ return self.domain_devtype_get(dom, 'vbd', vbd)
def domain_shadow_control(self, dom, op):
+ """Shadow page control.
+
+ dom domain
+ op operation
+ """
dom = int(dom)
return xc.shadow_control(dom, op)
- #============================================================================
def instance():
+ """Singleton constructor. Use this instead of the class constructor.
+ """
global inst
try:
inst
-#!/usr/bin/python
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Representation of a single domain.
from twisted.internet import defer
-import xen.ext.xc; xc = xen.ext.xc.new()
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
import xen.util.ip
import sxp
class XendDomainInfo:
"""Virtual machine object."""
+ STATE_OK = "ok"
+ STATE_TERMINATED = "terminated"
+
def __init__(self):
self.recreate = 0
self.config = None
self.blkif_backend = 0
self.netif_backend = 0
#todo: state: running, suspended
- self.state = 'running'
+ self.state = self.STATE_OK
#todo: set to migrate info if migrating
self.migrate = None
self.configs.append(val)
def destroy(self):
- if self.dom <= 0:
- return 0
+ """Completely destroy the vm.
+ """
+ self.cleanup()
+ return self.destroy_domain()
+
+ def destroy_domain(self):
+ """Destroy the vm's domain.
+ The domain will not finally go away unless all vm
+ devices have been released.
+ """
+ if self.dom is None: return 0
return xc.domain_destroy(dom=self.dom)
- def died(self):
- print 'died>', self.dom
+ def cleanup(self):
+ """Cleanup vm resources: release devices.
+ """
+ print 'cleanup>', self.dom
+ self.state = self.STATE_TERMINATED
self.release_devices()
+ def is_terminated(self):
+ """Check if a domain has been terminated.
+ """
+ return self.state == self.STATE_TERMINATED
+
def release_devices(self):
+ """Release all vm devices.
+ """
print 'release_devices>', self.dom
self.release_vifs()
self.release_vbds()
self.devices = {}
def release_vifs(self):
+ """Release vm virtual network devices (vifs).
+ """
print 'release_vifs>', self.dom
if self.dom is None: return
ctrl = xend.netif_get(self.dom)
ctrl.destroy()
def release_vbds(self):
+ """Release vm virtual block devices (vbds).
+ """
print 'release_vbds>', self.dom
if self.dom is None: return
ctrl = xend.blkif_get(self.dom)
"""
import os
-import xen.ext.xc
+import xen.lowlevel.xc
class XendNode:
def __init__(self):
- self.xc = xen.ext.xc.new()
+ self.xc = xen.lowlevel.xc.new()
def shutdown(self):
return 0
from twisted.internet import abstract
from twisted.internet import defer
-from xen.ext import xu
+from xen.lowlevel import xu
from xen.xend import sxp
from xen.xend import PrettyPrint
-import xen.ext.xc; xc = xen.ext.xc.new()
-from xen.ext import xu
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
+from xen.lowlevel import xu
from messages import msgTypeName
VIRQ_MISDIRECT = 0 # Catch-all interrupt for unbound VIRQs.
from twisted.internet import protocol
from twisted.protocols import telnet
-from xen.ext import xu
+from xen.lowlevel import xu
from xen.xend import EventServer
eserver = EventServer.instance()
import struct
-from xen.ext import xu
+from xen.lowlevel import xu
DEBUG = 0